| | /* ----------------------------------------------------------------------------------
Процесс авторегистрации абонентов
---------------------------------------------------------------------------------- */
#include "stdafx.h"
#include "../siglib/sys_inline.h"
@require "mpx.lua"
@include "../siglib/sys_signals.hh"
// Максимальное число номеров для регистрации
#define MAX_NUMBERLIST_LEN 30
// Разрешение таймера регистраций в миллисекундах
#define REG_CHECK_TIMEOUT 1000
// Актуальность регистраций в секундах
#define DEFAULT_REGISTRATION_TIMEOUT 180
// Повтор регистраций в секундах
#define NEXT_TRY_TIMEOUT 10
struct UserInfo
{
char Name[SHORT_LEN]; // Расширенное имя абонента
char Number[TEL_NUMBER_LEN]; // Номер абонента
char Password[BIG_LEN]; // Пароль абонента
WORD RegTimeout; // Таймер перерегистрации
BOOL RegProgress; // TRUE - Линия регистрируется
BOOL Registred; // Линия зарегистрирована
};
@BEGIN_DECLARE_PROCESS(AUTO_REGISTRATOR,"Auto registrator")
@FIELD(struct UserInfo, Users[MAX_NUMBERLIST_LEN],"Номера для регистрации")
@FIELD(WORD, UserCount, "Count of numbers")
@FIELD(WORD, RegTimeout, "Registration timeout")
@FIELD(WORD, RegQueue[MAX_NUMBERLIST_LEN], "Registration queue")
@FIELD(WORD, RegQueueLen, "Len of registration queue")
@FIELD(WORD, RegCurrent, "Регистрируемый номер")
@END_DECLARE_PROCESS()
@BEGIN_DECLARE_STATES()
@DEFINE_STATE(Init,"Init")
@DEFINE_STATE(Idle,"Idle")
@DEFINE_STATE(Register,"Registraton in progress")
@END_DECLARE_STATES()
@BEGIN_INIT_CONTEXT()
printf("------- BEGIN_INIT_CONTEXT\n");
@THIS()->UserCount = 0;
memset(@THIS()->Users, 0, MAX_NUMBERLIST_LEN*sizeof(struct UserInfo));
@THIS()->RegQueueLen = 0;
@THIS()->RegTimeout = DEFAULT_REGISTRATION_TIMEOUT;
@SET_STATE(Init)
@END_INIT_CONTEXT()
BOOL AppendUser(struct Call_SetRegInfo_struct* pUser)
{
WORD i;
printf("+++++ AppendUser(%s %s %s)\n", pUser->Number, pUser->Name, pUser->Password);
printf("+++++ Count=%d\n", @THIS()->UserCount);
for(i=0;i<@THIS()->UserCount;i++)
{
if(!stricmp(@THIS()->Users[i].Number, pUser->Number))
{
// Переопределяем
strcpy(@THIS()->Users[i].Name, pUser->Name);
strcpy(@THIS()->Users[i].Password, pUser->Password);
printf("+++++ 1\n");
return TRUE;
}
}
if(@THIS()->UserCount==MAX_NUMBERLIST_LEN)
{
printf("+++++ 1\n");
return FALSE;
}
strcpy(@THIS()->Users[@THIS()->UserCount].Number, pUser->Number);
strcpy(@THIS()->Users[@THIS()->UserCount].Name, pUser->Name);
strcpy(@THIS()->Users[@THIS()->UserCount].Password, pUser->Password);
@THIS()->UserCount++;
printf("+++++ Count=%d\n", @THIS()->UserCount);
return TRUE;
}
@BEGIN_CALL_CONTEXT()
switch(@CODE())
{
case REG_EXPIRE_TIMEOUT:
@THIS()->RegTimeout = *((WORD*)@PBUF());
return ERROR_noError;
case ADD_NUMBER_FOR_REGISTRATION:
{
struct Call_SetRegInfo_struct* pUser = (struct Call_SetRegInfo_struct*)@PBUF();
WORD i;
printf("+++++ AppendUser(%s %s %s)\n", pUser->Number, pUser->Name, pUser->Password);
printf("+++++ Count=%d\n", @THIS()->UserCount);
for(i=0;i<@THIS()->UserCount;i++)
{
if(!stricmp(@THIS()->Users[i].Number, pUser->Number))
{
// Переопределяем
strcpy(@THIS()->Users[i].Name, pUser->Name);
strcpy(@THIS()->Users[i].Password, pUser->Password);
printf("+++++ 1\n");
return ERROR_noError;
}
}
if(@THIS()->UserCount==MAX_NUMBERLIST_LEN)
{
printf("+++++ 1\n");
return ERROR_tooBig;
}
strcpy(@THIS()->Users[@THIS()->UserCount].Number, pUser->Number);
strcpy(@THIS()->Users[@THIS()->UserCount].Name, pUser->Name);
strcpy(@THIS()->Users[@THIS()->UserCount].Password, pUser->Password);
@THIS()->UserCount++;
printf("+++++ Count=%d\n", @THIS()->UserCount);
}
return ERROR_noError;
default:
return -1;
}
return ERROR_noError;
@END_CALL_CONTEXT()
@BEGIN_CONTEXT_TRACE()
char tmp[100];
WORD i;
@XML_TRACE("reg_queue_len", "%d", @THIS()->RegQueueLen)
tmp[0] = 0;
sprintf(tmp, "%d:", @THIS()->UserCount);
for(i=0;i<@THIS()->UserCount;i++)
{
sprintf(tmp+strlen(tmp), " %s", @THIS()->Users[i].Number);
}
@XML_TRACE("users", "%s", tmp)
@END_CONTEXT_TRACE()
// Обработка сигнала KL_START
@BEGIN_DECLARE_SIGNAL_ACTION(KL_START)
@SET_PERMANENT_TIMER(T0, REG_CHECK_TIMEOUT)
@SET_STATE(Idle)
@END_DECLARE_SIGNAL_ACTION()
// Обработка сигнала KL_STOP
@BEGIN_DECLARE_SIGNAL_ACTION(KL_STOP)
@END_DECLARE_SIGNAL_ACTION()
static void TryRegister(WORD LineNo)
{
// Посылаем запрос регистрации
@SIGNAL(RF_REGISTER, query)
@THIS()->Users[LineNo].RegProgress = TRUE;
strcpy(query->Name, @THIS()->Users[LineNo].Name);
strcpy(query->Number, @THIS()->Users[LineNo].Number);
strcpy(query->Password, @THIS()->Users[LineNo].Password);
query->Timeout = @THIS()->RegTimeout*2;
@THIS()->RegCurrent = LineNo;
@SEND(query)
}
static BOOL TryNextRegister()
{
// Если есть ожидающие регистрации, то регистрируем
if(@THIS()->RegQueueLen)
{
TryRegister(@THIS()->RegQueue[0]);
@THIS()->RegQueueLen--;
memcpy(@THIS()->RegQueue, @THIS()->RegQueue+1, @THIS()->RegQueueLen*sizeof(WORD));
return TRUE;
}
return FALSE;
}
@BEGIN_DECLARE_SIGNAL_ACTION(RF_COMPLETE, Register)
// Помечаем как зарегистрированного
@THIS()->Users[@THIS()->RegCurrent].Registred = TRUE;
@THIS()->Users[@THIS()->RegCurrent].RegTimeout = @THIS()->RegTimeout;
@THIS()->Users[@THIS()->RegCurrent].RegProgress = FALSE;
if(!TryNextRegister()) @SET_STATE(Idle)
@END_DECLARE_SIGNAL_ACTION()
@BEGIN_DECLARE_SIGNAL_ACTION(RF_FILED, Register)
// Откладываем повторную регистрацию
@THIS()->Users[@THIS()->RegCurrent].RegTimeout = NEXT_TRY_TIMEOUT;
@THIS()->Users[@THIS()->RegCurrent].RegProgress = FALSE;
if(!TryNextRegister()) @SET_STATE(Idle)
@END_DECLARE_SIGNAL_ACTION()
@BEGIN_DECLARE_SIGNAL_ACTION(T0, Register)
WORD i;
for(i=0;i<@THIS()->UserCount;i++)
{
if( @THIS()->Users[i].RegProgress ||
!@THIS()->Users[i].Number[0])
continue;
if(@THIS()->Users[i].RegTimeout)
@THIS()->Users[i].RegTimeout--;
else
{
// Добавляем в очередь для регистрации
@THIS()->Users[i].Registred = FALSE;
@THIS()->Users[i].RegProgress = TRUE;
@THIS()->RegQueue[@THIS()->RegQueueLen] = i;
@THIS()->RegQueueLen++;
}
}
@END_DECLARE_SIGNAL_ACTION()
@BEGIN_DECLARE_SIGNAL_ACTION(HR_PASSWORD_RQ, Idle)
WORD i;
@SIGNAL(HR_PASSWORD_ANS, ans)
ans->Hook = @PEVENT()->Hook;
for(i=0;i<@THIS()->UserCount;i++)
{
if(!strcmp(@THIS()->Users[i].Number, @PEVENT()->Name))
{
ans->Result = TRUE;
strcpy(ans->Password, @THIS()->Users[i].Password);
@NEXT_CONTEXT( @LMARK() )
@SEND(ans)
return;
}
}
ans->Result = FALSE;
@NEXT_CONTEXT( @LMARK() )
@SEND(ans)
@END_DECLARE_SIGNAL_ACTION()
@BEGIN_DECLARE_SIGNAL_ACTION(T0, Idle)
WORD i;
BOOL flag = FALSE;
for(i=0;i<@THIS()->UserCount;i++)
{
if(!@THIS()->Users[i].Number[0]) continue;
if(@THIS()->Users[i].RegTimeout)
@THIS()->Users[i].RegTimeout--;
else
{
@THIS()->Users[i].Registred = FALSE;
if(!flag)
{
TryRegister(i); // Регистрируем
flag = TRUE;
}
else
{
// Добавляем в очередь для регистрации
@THIS()->Users[i].RegProgress = TRUE;
@THIS()->RegQueue[@THIS()->RegQueueLen] = i;
@THIS()->RegQueueLen++;
}
}
}
if(flag){ @SET_STATE(Register) }
@END_DECLARE_SIGNAL_ACTION()
|
|