b9f3775e1b62a43c1cfc3a60f6b336be3356d994
[public/netxms.git] / src / server / core / sms.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2014 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: sms.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * SMS structure
27 */
28 typedef struct
29 {
30 TCHAR szRcpt[MAX_RCPT_ADDR_LEN];
31 TCHAR szText[160];
32 } SMS;
33
34 /**
35 * Static data
36 */
37 static Queue *m_pMsgQueue = NULL;
38 static BOOL (* m_DrvSendMsg)(const TCHAR *, const TCHAR *);
39 static void (* m_DrvUnload)();
40 static THREAD m_hThread = INVALID_THREAD_HANDLE;
41
42 /**
43 * Sender thread
44 */
45 static THREAD_RESULT THREAD_CALL SenderThread(void *pArg)
46 {
47 SMS *pMsg;
48
49 while(1)
50 {
51 pMsg = (SMS *)m_pMsgQueue->getOrBlock();
52 if (pMsg == INVALID_POINTER_VALUE)
53 break;
54
55 DbgPrintf(4, _T("SMS sender: rcpt=%s text=\"%s\""), pMsg->szRcpt, pMsg->szText);
56 int tries = 3;
57 do
58 {
59 if (m_DrvSendMsg(pMsg->szRcpt, pMsg->szText))
60 break;
61 DbgPrintf(3, _T("Failed to send SMS (will%s retry)"), (tries > 1) ? _T("") : _T(" not"));
62 }
63 while(--tries > 0);
64
65 if (tries == 0)
66 {
67 DbgPrintf(3, _T("Failed to send SMS (complete failure)"));
68 PostEvent(EVENT_SMS_FAILURE, g_dwMgmtNode, "s", pMsg->szRcpt);
69 }
70
71 free(pMsg);
72 }
73 return THREAD_OK;
74 }
75
76 /**
77 * Initialize SMS subsystem
78 */
79 void InitSMSSender()
80 {
81 TCHAR szDriver[MAX_PATH], szDrvConfig[MAX_CONFIG_VALUE];
82
83 ConfigReadStr(_T("SMSDriver"), szDriver, MAX_PATH, _T("<none>"));
84 ConfigReadStr(_T("SMSDrvConfig"), szDrvConfig, MAX_CONFIG_VALUE, _T(""));
85 if (_tcsicmp(szDriver, _T("<none>")))
86 {
87 TCHAR szErrorText[256];
88 HMODULE hModule;
89
90 hModule = DLOpen(szDriver, szErrorText);
91 if (hModule != NULL)
92 {
93 BOOL (* DrvInit)(const TCHAR *);
94
95 DrvInit = (BOOL (*)(const TCHAR *))DLGetSymbolAddr(hModule, "SMSDriverInit", szErrorText);
96 m_DrvSendMsg = (BOOL (*)(const TCHAR *, const TCHAR *))DLGetSymbolAddr(hModule, "SMSDriverSend", szErrorText);
97 m_DrvUnload = (void (*)())DLGetSymbolAddr(hModule, "SMSDriverUnload", szErrorText);
98 if ((DrvInit != NULL) && (m_DrvSendMsg != NULL) && (m_DrvUnload != NULL))
99 {
100 if (DrvInit(szDrvConfig))
101 {
102 m_pMsgQueue = new Queue;
103
104 m_hThread = ThreadCreateEx(SenderThread, 0, NULL);
105 }
106 else
107 {
108 nxlog_write(MSG_SMSDRV_INIT_FAILED, EVENTLOG_ERROR_TYPE, "s", szDriver);
109 DLClose(hModule);
110 }
111 }
112 else
113 {
114 nxlog_write(MSG_SMSDRV_NO_ENTRY_POINTS, EVENTLOG_ERROR_TYPE, "s", szDriver);
115 DLClose(hModule);
116 }
117 }
118 else
119 {
120 nxlog_write(MSG_DLOPEN_FAILED, EVENTLOG_ERROR_TYPE, "ss", szDriver, szErrorText);
121 }
122 }
123 }
124
125 /**
126 * Shutdown SMS sender
127 */
128 void ShutdownSMSSender()
129 {
130 if (m_pMsgQueue != NULL)
131 {
132 m_pMsgQueue->clear();
133 m_pMsgQueue->put(INVALID_POINTER_VALUE);
134 if (m_hThread != INVALID_THREAD_HANDLE)
135 ThreadJoin(m_hThread);
136 delete m_pMsgQueue;
137 }
138 }
139
140 /**
141 * Post SMS to queue
142 */
143 void NXCORE_EXPORTABLE PostSMS(const TCHAR *pszRcpt, const TCHAR *pszText)
144 {
145 if (m_pMsgQueue == NULL)
146 return;
147
148 SMS *pMsg = (SMS *)malloc(sizeof(SMS));
149 nx_strncpy(pMsg->szRcpt, pszRcpt, MAX_RCPT_ADDR_LEN);
150 nx_strncpy(pMsg->szText, pszText, 160);
151 m_pMsgQueue->put(pMsg);
152 }