]> git.stg.codes - stg.git/blob - projects/sgauth/web.cpp
Исправлена утечка ресурса (файлового дескриптора) при ошибке записи
[stg.git] / projects / sgauth / web.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  */
20
21  /*
22  $Revision: 1.7 $
23  $Date: 2010/03/15 12:58:17 $
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <time.h>
29 #include <libintl.h>
30
31 #include "web.h"
32 #include "common.h"
33 #include "ia_auth_c.h"
34
35 extern WEB * web;
36 extern IA_CLIENT_PROT * clnp;
37
38 #define LISTEN_PORT (5580)
39
40 #include "css.h"
41
42 //---------------------------------------------------------------------------
43 #ifndef WIN32
44 void * RunWeb(void *)
45 #else
46 unsigned long WINAPI RunWeb(void *)
47 #endif
48 {
49 while (1)
50     web->Run();
51 return NULL;
52 }
53 //---------------------------------------------------------------------------
54 WEB::WEB()
55     : res(0),
56       listenSocket(0),
57       outerSocket(0),
58       refreshPeriod(0),
59       listenWebAddr(0),
60       outerAddrLen(0)
61 {
62 #ifdef WIN32
63 res = WSAStartup(MAKEWORD(2,0), &wsaData);
64 #endif
65
66 for (int i = 0; i < DIR_NUM; i++)
67     dirName[i] = "-";
68
69 refreshPeriod = 5;
70 }
71 //---------------------------------------------------------------------------
72 void WEB::Start()
73 {
74 #ifdef WIN32
75 unsigned long pt;
76 CreateThread(
77     NULL,   // pointer to thread security attributes
78     16384,  // initial thread stack size, in bytes
79     RunWeb, // pointer to thread function
80     NULL,   // argument for new thread
81     0,      // CREATE_SUSPENDED, // creation flags
82     &pt     // pointer to returned thread identifier
83    );
84 #else
85 pthread_create(&thread, NULL, RunWeb, NULL);
86 #endif
87 }
88 //---------------------------------------------------------------------------
89 void WEB::PrepareNet()
90 {
91 listenSocket = socket(PF_INET, SOCK_STREAM, 0);
92 listenAddr.sin_family = AF_INET;
93 listenAddr.sin_port = htons(LISTEN_PORT);
94 listenAddr.sin_addr.s_addr = listenWebAddr;
95
96 int lng = 1;
97
98 #ifndef WIN32
99 if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
100     {
101     printf("Setsockopt Fail\n");
102     printf(">>> Error %s\n", strerror(errno));
103     }
104 #else
105 //??? TODO
106 #endif
107
108
109 res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
110
111 if (res == -1)
112     {
113     printf("Bind failed.\n");
114     exit(0);
115     }
116
117 res = listen(listenSocket, 0);
118 if (res == -1)
119     {
120     printf("Listen failed.\n");
121     exit(0);
122     }
123
124 outerAddrLen = sizeof(outerAddr);
125 }
126 //---------------------------------------------------------------------------
127 void WEB::SetRefreshPagePeriod(int p)
128 {
129 refreshPeriod = p;
130 if (refreshPeriod <= 0 || refreshPeriod > 24*3600)
131     refreshPeriod = 5;
132 }
133 //---------------------------------------------------------------------------
134 void WEB::SetListenAddr(uint32_t ip)
135 {
136 listenWebAddr = ip;
137 }
138 //---------------------------------------------------------------------------
139 void WEB::Run()
140 {
141 PrepareNet();
142 char recvBuffer[4096];
143 while (1)
144     {
145     outerSocket = accept(listenSocket, (struct sockaddr*)&outerAddr, &outerAddrLen);
146     if (outerSocket == -1)
147         {
148         printf(">>> Error %s\n", strerror(errno));
149         continue;
150         }
151     recv(outerSocket, recvBuffer, sizeof(recvBuffer), 0);
152
153     if (strncmp(recvBuffer, "GET /sgauth.css", strlen("GET /sgauth.css")) == 0)
154         {
155         SendCSS();
156         //printf("(1) recvBuffer=%s\n", recvBuffer);
157         }
158     else if (strncmp(recvBuffer, "GET /disconnect", strlen("GET /disconnect")) == 0)
159         {
160         clnp->Disconnect();
161         Redirect("/");
162         //printf("(2) recvBuffer=%s\n", recvBuffer);
163         }
164     else if (strncmp(recvBuffer, "GET /connect", strlen("GET /connect")) == 0)
165         {
166         clnp->Connect();
167         Redirect("/");
168         //printf("(3) recvBuffer=%s\n", recvBuffer);
169         }
170     else if (strncmp(recvBuffer, "GET /exit", strlen("GET /exit")) == 0)
171         {
172         Redirect("/");
173         clnp->Disconnect();
174         #ifdef WIN32
175         Sleep(1000);
176         #else
177         usleep(1000000);
178         #endif
179         exit(0);
180         }
181     else
182        {
183        SendReply();
184        //printf("(4) recvBuffer=%s\n", recvBuffer);
185        }
186
187     #ifdef WIN32
188     closesocket(outerSocket);
189     #else
190     close(outerSocket);
191     #endif
192     }
193 }
194 //---------------------------------------------------------------------------
195 int WEB::Redirect(const char * url)
196 {
197 const char * redirect =
198     "HTTP/1.0 200 OK\n"
199     "Content-Type: text/html\n"
200     "Connection: close"
201     "\n\n"
202     "<html>\n"
203     "<head>\n"
204     "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
205     "</head>\n"
206     "<body>\n"
207     "</body></html>\n\n";
208
209 char buff[2000];
210 sprintf(buff, redirect, url);
211 send(outerSocket, buff, strlen(buff), 0);
212
213 return 0;
214 }
215 //---------------------------------------------------------------------------
216 int WEB::SendReply()
217 {
218 int j, rowNum;
219
220 const char * replyHeader =
221     "HTTP/1.0 200 OK\n"
222     "Content-Type: text/html\n"
223     "Connection: close"
224     "\n\n"
225     "<html>\n"
226     "<head>\n"
227     "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
228     "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
229     "<title>sgauth</title>\n"
230     "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
231     "</head>\n"
232     "<body>\n"
233     "<H3>Stargazer</H3><p>\n";
234
235 const char * replyFooter = "</body></html>\n\n";
236
237 char replyHeaderBuffer[2000];
238 sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
239
240 send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
241
242 char str[512];
243
244 int st = clnp->GetAuthorized();
245
246 sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
247 res = send(outerSocket, str, strlen(str), 0);
248
249 sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
250 res = send(outerSocket, str, strlen(str), 0);
251
252 sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
253 res = send(outerSocket, str, strlen(str), 0);
254
255 sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
256 res = send(outerSocket, str, strlen(str), 0);
257
258 sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
259 res = send(outerSocket, str, strlen(str), 0);
260
261 sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
262 res = send(outerSocket, str, strlen(str), 0);
263
264 sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
265         gettext("PrepaidTraffic"),
266         ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
267 res = send(outerSocket, str, strlen(str), 0);
268
269 sprintf(str, "<TABLE id=\"TraffTable\">\n");
270 res = send(outerSocket, str, strlen(str), 0);
271 sprintf(str, "    <TR id=\"TraffTableCaptionRow\">\n");
272 res = send(outerSocket, str, strlen(str), 0);
273 sprintf(str, "       <TD id=\"TraffTableCaptionCellC\">&nbsp;</TD>\n");
274 res = send(outerSocket, str, strlen(str), 0);
275
276 rowNum = 0;
277 for (j = 0; j < DIR_NUM; j++)
278     {
279     if (dirName[j][0] == 0)
280         continue;
281     string s;
282     KOIToWin(dirName[j], &s);// +++++++++ sigsegv ==========   TODO too long dir name crashes sgauth
283     sprintf(str, "       <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
284     send(outerSocket, str, strlen(str), 0);
285     }
286
287 sprintf(str,"    </TR>\n");
288 send(outerSocket, str, strlen(str), 0);
289
290 sprintf(str,"    <TR id=\"TraffTableUMRow\">\n");
291 send(outerSocket, str, strlen(str), 0);
292
293 sprintf(str,"        <TD id=\"TraffTableUMCellC\">%s</TD>\n", gettext("Month Upload"));
294 send(outerSocket, str, strlen(str), 0);
295
296 rowNum = 0;
297 for (j = 0; j < DIR_NUM; j++)
298     {
299     if (dirName[j][0] == 0)
300         continue;
301     sprintf(str,"        <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
302     res = send(outerSocket, str, strlen(str), 0);
303     }
304
305 sprintf(str,"    </TR>\n");
306 res = send(outerSocket, str, strlen(str), 0);
307 sprintf(str,"    <TR id=\"TraffTableDMRow\">\n");
308 res = send(outerSocket, str, strlen(str), 0);
309 sprintf(str,"        <TD id=\"TraffTableDMCellC\">%s</TD>\n", gettext("Month Download"));
310 res = send(outerSocket, str, strlen(str), 0);
311
312 rowNum = 0;
313 for (j = 0; j < DIR_NUM; j++)
314     {
315     if (dirName[j][0] == 0)
316         continue;
317     sprintf(str,"        <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
318     res = send(outerSocket, str, strlen(str), 0);
319     }
320 sprintf(str,"    </TR>\n");
321 res = send(outerSocket, str, strlen(str), 0);
322
323
324 sprintf(str,"    <TR id=\"TraffTableUSRow\">\n");
325 res = send(outerSocket, str, strlen(str), 0);
326 sprintf(str,"        <TD id=\"TraffTableUSCellC\">%s</TD>\n", gettext("Session Upload"));
327 res = send(outerSocket, str, strlen(str), 0);
328
329 rowNum = 0;
330 for (j = 0; j < DIR_NUM; j++)
331     {
332     if (dirName[j][0] == 0)
333         continue;
334     sprintf(str,"        <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
335     res = send(outerSocket, str, strlen(str), 0);
336     }
337
338 sprintf(str,"    </TR>\n");
339 res = send(outerSocket, str, strlen(str), 0);
340 sprintf(str,"    <TR id=\"TraffTableDSRow\">\n");
341 res = send(outerSocket, str, strlen(str), 0);
342 sprintf(str,"        <TD id=\"TraffTableDSCellC\">%s</TD>\n", gettext("Session Download"));
343 res = send(outerSocket, str, strlen(str), 0);
344
345 rowNum = 0;
346 for (j = 0; j < DIR_NUM; j++)
347     {
348     if (dirName[j][0] == 0)
349         continue;
350     sprintf(str,"        <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
351     res = send(outerSocket, str, strlen(str), 0);
352     }
353
354 sprintf(str,"    </TR>\n");
355 res = send(outerSocket, str, strlen(str), 0);
356
357 sprintf(str,"</TABLE>\n");
358 res = send(outerSocket, str, strlen(str), 0);
359
360 rowNum = 0;
361 if (!messages.empty())
362     {
363     sprintf(str,"    <TABLE id=\"MessagesTable\">\n");
364     res = send(outerSocket, str, strlen(str), 0);
365
366     sprintf(str,"        <TR id=\"MessagesTableRowC\">\n");
367     send(outerSocket, str, strlen(str), 0);
368     sprintf(str,"            <TD>Date</TD>\n");
369     send(outerSocket, str, strlen(str), 0);
370     sprintf(str,"            <TD>Text</TD>\n");
371     send(outerSocket, str, strlen(str), 0);
372     sprintf(str,"        </TR>\n");
373     send(outerSocket, str, strlen(str), 0);
374
375     list<STG_MESSAGE>::reverse_iterator it;
376     it = messages.rbegin();
377     while (it != messages.rend())
378         {
379         sprintf(str,"        <TR id=\"MessagesTableRow%d\">\n", rowNum);
380         send(outerSocket, str, strlen(str), 0);
381         sprintf(str,"            <TD>%s</TD>\n", it->recvTime.c_str());
382         send(outerSocket, str, strlen(str), 0);
383         sprintf(str,"            <TD>%s</TD>\n", it->msg.c_str());
384         send(outerSocket, str, strlen(str), 0);
385         sprintf(str,"        </TR>\n");
386         send(outerSocket, str, strlen(str), 0);
387         ++it;
388         ++rowNum;
389         }
390
391     sprintf(str,"   </TABLE>\n");
392     res = send(outerSocket, str, strlen(str), 0);
393     }
394
395 time_t t = time(NULL);
396 sprintf(str,"Îáíîâëåíî: %s</b>" , ctime(&t));
397 res = send(outerSocket, str, strlen(str), 0);
398
399 send(outerSocket, replyFooter, strlen(replyFooter), 0);
400
401 return 0;
402 }
403 //---------------------------------------------------------------------------
404 int WEB::SendCSS()
405 {
406 const char * replyHeader =
407     "HTTP/1.0 200 OK\n"
408     "Content-Type: text/css\n"
409     "Connection: close\n\n";
410
411 const char * replyFooter= "\n\n";
412
413 send(outerSocket, replyHeader, strlen(replyHeader), 0);
414 send(outerSocket, css, strlen(css), 0);
415 send(outerSocket, replyFooter, strlen(replyFooter), 0);
416
417 return 0;
418 }
419 //---------------------------------------------------------------------------
420 void WEB::SetDirName(const string & dn, int n)
421 {
422 web->dirName[n] =  dn;
423 }
424 //---------------------------------------------------------------------------
425 void WEB::AddMessage(const string & message, int type)
426 {
427 time_t t = time(NULL);
428 STG_MESSAGE m;
429
430 m.msg = message;
431 m.type = type;
432 m.recvTime = ctime(&t);
433
434 messages.push_back(m);
435
436 if (messages.size() > MAX_MESSAGES)
437     messages.pop_front();
438
439 }
440 //---------------------------------------------------------------------------
441 void WEB::UpdateStat(const LOADSTAT & ls)
442 {
443 memcpy((void*)&(WEB::ls), &ls, sizeof(LOADSTAT));
444 }
445 //---------------------------------------------------------------------------
446