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

Contents of /innwebd/base_passive.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations)
Sat Jul 3 13:56:04 2004 UTC (21 years, 8 months ago) by sysadm
Branch: MAIN
Changes since 1.2: +35 -6 lines
Content type: text/x-c++src
Add thread_pool

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

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