/[LeafOK_CVS]/innwebd/base_passive.cpp
ViewVC logotype

Contents of /innwebd/base_passive.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Fri Apr 11 17:14:49 2008 UTC (17 years, 11 months ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +14 -10 lines
Content type: text/x-c++src
Update copyright
Add extra log for exception

1 /*******************************************************/
2 /* */
3 /* LeafOK Innbbsd */
4 /* */
5 /* Copyright (C) LeafOK.com, 2003-2008 */
6 /* */
7 /* http://www.leafok.com */
8 /* */
9 /*******************************************************/
10
11 #include "StdAfx.h"
12 #include ".\base_passive.h"
13 #include ".\base_active.h"
14
15 using namespace std;
16
17 // UINT base_passive::uThreadCount = 0;
18
19 base_passive::base_passive(void)
20 {
21 }
22
23 base_passive::~base_passive(void)
24 {
25 this->s_close();
26 this->db_close();
27 }
28
29 int base_passive::s_connect(const char* hostaddr, unsigned int port)
30 {
31 SOCKADDR_IN sin;
32
33 if (this->isConnected)
34 {
35 this->s_close();
36 }
37
38 //Create a TCP/IP socket
39 if ((this->s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
40 {
41 syslog << logfile::log_head << "Cannot create socket" << endl;
42 return -1;
43 }
44
45 //fill in sockaddr_in struct
46
47 sin.sin_family = PF_INET;
48 sin.sin_port = htons(port);
49 sin.sin_addr.s_addr = (strlen(hostaddr) > 0 ? inet_addr(hostaddr) : INADDR_ANY);
50
51 //bind the socket
52 if(bind(this->s, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
53 {
54 syslog << logfile::log_head << "Cannot bind" << endl;
55 return -1;
56 }
57
58 if(listen(this->s,5) == SOCKET_ERROR)
59 {
60 syslog << logfile::log_head << "Cannot listen" << endl;
61 return -1;
62 }
63
64 strcpy(this->hostaddr,hostaddr);
65 this->port = port;
66
67 this->isConnected = true;
68
69 return 0;
70 }
71
72 int base_passive::s_close(void)
73 {
74 if (!this->isConnected)
75 return 0;
76
77 if (closesocket(this->s) == SOCKET_ERROR)
78 {
79 syslog << logfile::log_head << "Close socket error" << endl;
80 }
81
82 this->isConnected = false;
83
84 return 0;
85 }
86
87 int base_passive::work()
88 {
89 HANDLE hThreadCurrent;
90 ULONG ulThreadId;
91 base_passive* p;
92 SOCKADDR_IN sin;
93 int namelen;
94
95 if (this->running)
96 return 1;
97
98 if (this->load_priv() != 0)
99 return -1;
100
101 this->SetThreadPool(new thread_pool(MAX_CLIENT));
102 if (this->p_ThreadPool->GetLastError() != 0)
103 {
104 return -1;
105 }
106
107 if (this->s_connect(this->w_address,this->w_port) == 0)
108 {
109 this->Startup();
110
111 syslog << logfile::log_head << "Listen at port [" << this->w_port << "]" << endl;
112
113 while(!this->IsShutdown())
114 {
115 if ((p = this->new_client()) == NULL)
116 {
117 syslog << logfile::log_head << "Assign new client failed" << endl;
118 continue;
119 }
120
121 p->SetParentThread(this);
122 p->configure(this->innd_id,this->innd_name,this->innd_server,this->innd_uid,this->w_address,this->w_port,this->w_conn_str);
123
124 this->running = true;
125
126 this->GetParentThread()->GetThreadPool()->SetThreadStatus(GetCurrentThreadId(),thread_pool::S_WAITING);
127
128 namelen = sizeof(sin);
129 if ((p->s = accept(this->s,(LPSOCKADDR)&sin,&namelen)) == INVALID_SOCKET)
130 {
131 syslog << logfile::log_head << "Socket accept failed (" << GetLastError() <<")" << endl;
132 this->unload_priv();
133 this->Shutdown();
134 this->running = false;
135 return -2;
136 }
137
138 if (this->IsShutdown())
139 {
140 break;
141 }
142
143 this->GetParentThread()->GetThreadPool()->SetThreadStatus(GetCurrentThreadId(),thread_pool::S_WORKING);
144
145 strcpy(p->hostaddr,inet_ntoa(sin.sin_addr));
146 p->port = sin.sin_port;
147 p->isConnected = true;
148
149 // strcpy(p->w_conn_str,this->w_conn_str);
150
151 if (this->get_priv(p)!=0)
152 {
153 p->s_send("502 Load access file failed.\r\n");
154 delete(p);
155 continue;
156 }
157
158 if (!p->check_priv())
159 {
160 p->s_send("502 You are not in my access file.\r\n");
161 delete(p);
162 continue;
163 }
164
165 // if (base_passive::uThreadCount < MAX_CLIENT)
166 if (this->GetThreadPool()->GetThreadCount() < MAX_CLIENT)
167 {
168 if (hThreadCurrent = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)base_passive::AcceptThread,(LPVOID)p,0,&ulThreadId))
169 {
170 CloseHandle(hThreadCurrent);
171 syslog << logfile::log_head << "Create accept thread ... OK" << endl;
172 }
173 else
174 {
175 delete(p);
176 syslog << logfile::log_head << "Create accept thread ... Failed" << endl;
177 }
178 }
179 else
180 {
181 p->s_send("502 Too many connections\r\n");
182 delete(p);
183 }
184 }
185 delete(p);
186 Sleep(1000*5); // Wait several seconds for all threads to exit
187 }
188 this->s_close();
189
190 this->unload_priv();
191
192 this->running = false;
193
194 return 0;
195 }
196
197 DWORD base_passive::AcceptThread(LPVOID pParam)
198 {
199 base_passive* p;
200
201 try
202 {
203 p = (base_passive*)pParam;
204
205 p->ulMainThreadId = GetCurrentThreadId();
206
207 syslog << logfile::log_head << "Accept connection from " << p->hostaddr
208 << ":" << p->port << endl;
209
210 if (p->GetParentThread()->GetThreadPool()->AddThread(GetCurrentThreadId(), CLOCKS_PER_SEC * 30) != 0)
211 {
212 syslog << logfile::log_head << "Register thread ... Failed" << endl;
213 }
214 p->GetParentThread()->GetThreadPool()->SetThreadStatus(GetCurrentThreadId(),thread_pool::S_WORKING);
215
216 if (p->db_env_init() == 0)
217 {
218 p->Accept();
219 }
220 else
221 {
222 syslog << logfile::log_head << "DB_ENV_INIT failed" << endl;
223 }
224
225 if (p->GetParentThread()->GetThreadPool()->RemoveThread(GetCurrentThreadId()) != 0)
226 {
227 syslog << logfile::log_head << "Unregister thread ... Failed" << endl;
228 }
229 // base_passive::uThreadCount--;
230
231 delete(p);
232 syslog << logfile::log_head << "Delete accept thread ... OK" << endl;
233 }
234 catch(CException* e)
235 {
236 char strErrMsg[1024];
237 e->GetErrorMessage(strErrMsg,1024);
238 syslog << logfile::log_head << "Error in AcceptThread() [" << strErrMsg << "]" << endl;
239 e->Delete();
240 return -1;
241 }
242
243 return 0;
244 }
245
246 int base_passive::get_priv(base_passive* p)
247 {
248 try
249 {
250 //Default value
251 strcpy(p->access.ip,p->hostaddr);
252 p->access.control = false;
253 p->access.get = false;
254 p->access.post = false;
255 p->access.ihave = false;
256
257 //Check access list
258 for (int i=1; i<this->access_array.GetCount(); i++)
259 {
260 if (strcmp(this->access_array[i]->ip,p->hostaddr) == 0)
261 {
262 p->access = *(this->access_array[i]);
263 break;
264 }
265 }
266 }
267 catch(CException* e)
268 {
269 char strErrMsg[1024];
270 e->GetErrorMessage(strErrMsg,1024);
271 syslog << logfile::log_head << "Error in get_priv() [" << strErrMsg << "]" << endl;
272 e->Delete();
273 return -1;
274 }
275
276 return 0;
277 }
278
279 int base_passive::load_priv(void)
280 {
281 CRecordset RS;
282 CString sql;
283 CDBVariant dbVar;
284 Access_STRUCT* p_access;
285
286 try
287 {
288 if (this->db_open(this->w_conn_str) == 0)
289 {
290 RS.m_pDatabase = &(this->Db);
291 }
292 else
293 return -2;
294
295 //Check access list
296 sql = "select * from innd_access where enable order by ip";
297 RS.Open(CRecordset::snapshot,sql,CRecordset::readOnly);
298 this->access_array.SetSize(RS.GetRecordCount());
299 while(!RS.IsEOF())
300 {
301 p_access = new Access_STRUCT();
302
303 RS.GetFieldValue("ip",dbVar,SQL_C_CHAR);
304 strcpy(p_access->ip,*(dbVar.m_pstring));
305 RS.GetFieldValue("control",dbVar,SQL_C_SSHORT);
306 p_access->control = (dbVar.m_iVal!=0);
307 RS.GetFieldValue("get",dbVar,SQL_C_SSHORT);
308 p_access->get = (dbVar.m_iVal!=0);
309 RS.GetFieldValue("post",dbVar,SQL_C_SSHORT);
310 p_access->post = (dbVar.m_iVal!=0);
311 RS.GetFieldValue("ihave",dbVar,SQL_C_SSHORT);
312 p_access->ihave = (dbVar.m_iVal!=0);
313
314 this->access_array.Add(p_access);
315 RS.MoveNext();
316 }
317 RS.Close();
318
319 this->db_close();
320 }
321 catch(CException* e)
322 {
323 char strErrMsg[1024];
324 e->GetErrorMessage(strErrMsg,1024);
325 syslog << logfile::log_head << "Error in load_priv() [" << strErrMsg << "]" << endl;
326 e->Delete();
327 return -1;
328 }
329
330 return 0;
331 }
332
333 int base_passive::unload_priv(void)
334 {
335 Access_STRUCT* p_access;
336
337 try
338 {
339 for (int i=1; i<this->access_array.GetCount();i++)
340 {
341 p_access = this->access_array[i];
342 delete (p_access);
343 }
344 this->access_array.RemoveAll();
345 }
346 catch(CException* e)
347 {
348 char strErrMsg[1024];
349 e->GetErrorMessage(strErrMsg,1024);
350 syslog << logfile::log_head << "Error in unload_priv() [" << strErrMsg << "]" << endl;
351 e->Delete();
352 return -1;
353 }
354
355 return 0;
356 }
357
358 int base_passive::w_call(void)
359 {
360 this->work();
361 return 0;
362 }
363
364 bool base_passive::check_priv(void)
365 {
366 return this->access.get;
367 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1