- 1 #include "SoapWebServer.h"
- 2 //#include "soap.nsmap"
- 3
- 4 SOAP_NMAC struct Namespace namespaces[] = {
- 5 {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL},
- 6 {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL},
- 7 {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
- 8 {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
- 9 {NULL, NULL, NULL, NULL}
- 10 };
- 11
- 12 int TestAPI(Request& request)
- 13 {
- 14 char* body = NULL;
- 15 size_t body_len = request.GetBody(&body);
- 16
- 17 Response res(request);
- 18 res.SetContentType("text/json");
- 19 res.Send("{\"name\":\"bobo\",\"age\": 50}");
- 20
- 21 return SOAP_OK;
- 22 }
- 23
- 24 CSoapWebServer::CSoapWebServer():
- 25 m_pSoap(NULL),
- 26 m_bExit(false),
- 27 m_ListenThread(nullptr),
- 28 m_iClientCount(0)
- 29 {
- 30 for (int i = 0; i < MaxThreadCount; ++i)
- 31 {
- 32 m_ServeThread[i] = nullptr;
- 33 }
- 34 }
- 35
- 36 CSoapWebServer::~CSoapWebServer()
- 37 {
- 38
- 39 }
- 40 void CSoapWebServer::ClearURI()
- 41 {
- 42 m_service.ClearURI();
- 43 }
- 44
- 45 void CSoapWebServer::ResetURI( const char* URI )
- 46 {
- 47 if (URI)
- 48 {
- 49 m_service.UnRegisteURI(URI);
- 50 }
- 51 }
- 52
- 53 void CSoapWebServer::SetURI( const char* URI,RequestProcessFunc fun, void * user)
- 54 {
- 55 if (!URI || !fun)
- 56 {
- 57 return;
- 58 }
- 59
- 60 m_service.RegisteURI(URI,fun, user);
- 61 }
- 62
- 63 void CSoapWebServer::SetURI(const char* URI, RequestProcessFunction & fun)
- 64 {
- 65 if (!URI || !fun)
- 66 {
- 67 return;
- 68 }
- 69
- 70 m_service.RegisteURI(URI,fun);
- 71 }
- 72
- 73 bool CSoapWebServer::StartService(const char* ip,unsigned int port)
- 74 {
- 75 //StopService();
- 76 m_bExit = false;
- 77 do
- 78 {
- 79 m_pSoap = soap_new();
- 80 if (NULL == m_pSoap)
- 81 {
- 82 break;
- 83 }
- 84
- 85 soap_init1(m_pSoap, SOAP_C_UTFSTRING);
- 86 m_pSoap->bind_flags = SO_REUSEADDR;
- 87 m_pSoap->send_timeout = SendTimeout;
- 88 m_pSoap->recv_timeout = RecvTimeout;
- 89 m_pSoap->accept_timeout = AcceptTimeout;
- 90 m_pSoap->imode = SOAP_C_UTFSTRING;
- 91
- 92 m_pSoap->namespaces = namespaces;
- 93 soap_set_local_namespaces(m_pSoap);
- 94
- 95 m_service.Hook(m_pSoap);
- 96 {
- 97 FreeSoapFunction fun((FreeSoapFunction)std::tr1::bind(
- 98 &CSoapWebServer::PushSoap, this, std::tr1::placeholders::_1));
- 99 m_service.RegisterFreeSoap(fun);
- 100 }
- 101
- 102 SOAP_SOCKET serverSocket = soap_bind(m_pSoap,ip,port,200);
- 103 if (serverSocket == SOAP_INVALID_SOCKET)
- 104 {
- 105 printf("err soap_bind, %s:%u\n", ip, port);
- 106 break;
- 107 }
- 108 printf("soap bind %s:%u\n", ip, port);
- 109
- 110 if (!StartThread())
- 111 {
- 112 printf("err StartThread\n");
- 113 break;
- 114 }
- 115 printf("start success\n");
- 116 return true;
- 117 } while (false);
- 118 printf("err start failed\n");
- 119 StopService();
- 120 return false;
- 121 }
- 122 void CSoapWebServer::StopService()
- 123 {
- 124 m_bExit = true;
- 125 CloseThread();
- 126 m_iClientCount = 0;
- 127
- 128 m_service.ClearURI();
- 129 FreeSoapAll();
- 130 if (NULL != m_pSoap)
- 131 {
- 132 soap_destroy(m_pSoap);
- 133 soap_end(m_pSoap);
- 134 soap_done(m_pSoap);
- 135 soap_free(m_pSoap);
- 136 m_pSoap = NULL;
- 137 }
- 138 }
- 139 bool CSoapWebServer::StartThread()
- 140 {
- 141 //>开启service接受执行线程
- 142 m_ListenThread = new std::thread(
- 143 &CSoapWebServer::ServiceListenThread,this);
- 144
- 145 int iThreadCount = 10;
- 146 if( iThreadCount > MaxThreadCount)
- 147 {
- 148 iThreadCount = MaxThreadCount;
- 149 }
- 150 else if(iThreadCount == 0)
- 151 {
- 152 iThreadCount = 1;
- 153 }
- 154
- 155 for (int i = 0; i < iThreadCount; ++i)
- 156 {
- 157 soap* pSoap = soap_copy(m_pSoap);
- 158 THREAD_INFO* info = new(std::nothrow)THREAD_INFO;
- 159 if (info == NULL)
- 160 {
- 161 return false;
- 162 }
- 163 info->soap_listen = m_pSoap;
- 164 info->soap_client = pSoap;
- 165 info->pThis = this;
- 166 m_ServeThread[i] = new std::thread(
- 167 &CSoapWebServer::ServiceServeThread, this, info);
- 168 }
- 169 return true;
- 170 }
- 171
- 172 void CSoapWebServer::CloseThread()
- 173 {
- 174 m_cvClient.notify_all();
- 175 if (m_ListenThread)
- 176 {
- 177 m_ListenThread->join();
- 178 delete m_ListenThread;
- 179 m_ListenThread = nullptr;
- 180 }
- 181
- 182 for (int i = 0; i < MaxThreadCount; i++)
- 183 {
- 184 if(m_ServeThread[i])
- 185 {
- 186 m_ServeThread[i]->join();
- 187 delete m_ServeThread[i];
- 188 m_ServeThread[i] = nullptr;
- 189 }
- 190 }
- 191 }
- 192 void CSoapWebServer::ServiceListenThread()
- 193 {
- 194 Listen();
- 195 return ;
- 196 }
- 197 void CSoapWebServer::Listen()
- 198 {
- 199 if (NULL == m_pSoap)
- 200 {
- 201 return ;
- 202 }
- 203 CLIENT_INFO clientInfo;
- 204 while (!m_bExit)
- 205 {
- 206 clientInfo.socket = soap_accept(m_pSoap);
- 207 if (clientInfo.socket != SOAP_INVALID_SOCKET )
- 208 {
- 209 std::unique_lock<std::mutex> guard(m_listMt);
- 210 clientInfo.ip = m_pSoap->ip;
- 211 clientInfo.port = m_pSoap->port;
- 212 m_acceptClientList.push(clientInfo);
- 213 ++m_iClientCount;
- 214 m_cvClient.notify_one();
- 215 }
- 216 }
- 217 }
- 218
- 219 void CSoapWebServer::ServiceServeThread(THREAD_INFO* pParam )
- 220 {
- 221 if (NULL == pParam)
- 222 {
- 223 return ;
- 224 }
- 225 THREAD_INFO* info = (THREAD_INFO*)pParam;
- 226 CSoapWebServer *pThis = info->pThis;
- 227
- 228 if(NULL == pThis)
- 229 {
- 230 return ;
- 231 }
- 232 ExecuteServe(info);
- 233
- 234 delete info;
- 235
- 236 return ;
- 237 }
- 238 void CSoapWebServer::ExecuteServe(THREAD_INFO* info )
- 239 {
- 240 const int iTempSockCount = 1;
- 241 CLIENT_INFO tempClientArr[iTempSockCount] = {};
- 242 int end_pos = 0;
- 243 struct soap* soap = NULL;
- 244
- 245 soap = info->soap_client;
- 246 int ret = SOAP_OK;
- 247
- 248 while (!m_bExit)
- 249 {
- 250 {
- 251 std::unique_lock<std::mutex> guard(m_listMt);
- 252 if (m_acceptClientList.empty())
- 253 {
- 254 m_cvClient.wait(guard);
- 255 }
- 256 for (end_pos=0;
- 257 end_pos<iTempSockCount && !m_acceptClientList.empty();
- 258 ++end_pos )
- 259 {
- 260 tempClientArr[end_pos] = m_acceptClientList.front();
- 261 m_acceptClientList.pop();
- 262 --m_iClientCount;
- 263 }
- 264 }
- 265
- 266 for (int i = 0 ; i < end_pos; ++i)
- 267 {
- 268 soap->socket = tempClientArr[i].socket;
- 269 soap->ip = tempClientArr[i].ip;
- 270 soap->port = tempClientArr[i].port;
- 271 if(!soap_valid_socket(soap->socket))
- 272 {
- 273 continue;
- 274 }
- 275
- 276 if ((ret=BeginServe(soap)) != SOAP_OK)
- 277 {
- 278 //printf("serve error.code:%d msg:%s\n", soap->error,*(soap_faultstring(soap)));
- 279 }
- 280
- 281 if (ret == SOAP_STOP/*(int)soap->user == RESPONSE_MODE_ASYN*/)
- 282 {//异步
- 283 //获取一个soap
- 284 soap = PopSoap();
- 285 if (soap == NULL)
- 286 {//缓存没有,拷贝一个
- 287 soap = soap_copy(info->soap_listen);
- 288 }
- 289 }
- 290 else
- 291 {
- 292 EndServe(soap);
- 293 }
- 294
- 295 soap_destroy(soap);
- 296 soap_end(soap);
- 297 }
- 298 }
- 299
- 300 //回收
- 301 PushSoap(soap);
- 302 }
- 303
- 304 int CSoapWebServer::SoapServ( struct soap* soap )
- 305 {
- 306 #ifndef WITH_FASTCGI
- 307 unsigned int k = soap->max_keep_alive;
- 308 #endif
- 309 do
- 310 {
- 311 #ifndef WITH_FASTCGI
- 312 if (soap->max_keep_alive > 0 && !--k)
- 313 {
- 314 soap->keep_alive = 0;
- 315 }
- 316 #endif
- 317 if (soap_begin_serve(soap))
- 318 {
- 319 if (soap->error >= SOAP_STOP)
- 320 {
- 321 continue;
- 322 }
- 323 return soap->error;
- 324 }
- 325
- 326 #ifdef WITH_FASTCGI
- 327 soap_destroy(soap);
- 328 soap_end(soap);
- 329 } while (1);
- 330 #else
- 331 } while (soap->keep_alive);
- 332 #endif
- 333 return SOAP_OK;
- 334 }
- 335
- 336 int CSoapWebServer::BeginServe(struct soap* soap)
- 337 {
- 338 void * user = soap->user;
- 339 long ret = RESPONSE_MODE_SYN;
- 340
- 341 soap_begin(soap);
- 342 if (soap_begin_recv(soap)
- 343 || soap_envelope_begin_in(soap)
- 344 || soap_recv_header(soap)
- 345 || soap_body_begin_in(soap))
- 346 { if (soap->error < SOAP_STOP)
- 347 {
- 348 #ifdef WITH_FASTCGI
- 349 (void)soap_send_fault(soap);
- 350 #else
- 351 return soap_send_fault(soap);
- 352 #endif
- 353 }
- 354 }
- 355
- 356 ret = (long)soap->user;
- 357 soap->user = user;
- 358
- 359 return (ret==RESPONSE_MODE_ASYN) ? SOAP_STOP: SOAP_OK;
- 360 }
- 361
- 362 int CSoapWebServer::EndServe(struct soap* soap)
- 363 {
- 364 return soap_closesock(soap);
- 365 }
- 366
- 367 struct soap* CSoapWebServer::PopSoap(void)
- 368 {
- 369 struct soap * soap = NULL;
- 370 std::unique_lock<std::mutex> guard(m_listMt);
- 371 if (m_soapList.empty())
- 372 {
- 373 return NULL;
- 374 }
- 375 soap = m_soapList.front();
- 376 m_soapList.pop();
- 377
- 378 return soap;
- 379 }
- 380
- 381 void CSoapWebServer::PushSoap(struct soap* soap)
- 382 {
- 383 if (soap == NULL)
- 384 {
- 385 return ;
- 386 }
- 387
- 388 std::unique_lock<std::mutex> guard(m_listMt);
- 389 m_soapList.push(soap);
- 390 }
- 391
- 392 void CSoapWebServer::FreeSoapAll(void)
- 393 {
- 394 std::queue<struct soap*> lsoap;
- 395 {
- 396 std::unique_lock<std::mutex> guard(m_listMt);
- 397 lsoap = m_soapList;
- 398 while (!m_soapList.empty())
- 399 {
- 400 m_soapList.pop();
- 401 }
- 402 }
- 403
- 404 struct soap * soap;
- 405 while (!lsoap.empty())
- 406 {
- 407 soap = lsoap.front();
- 408
- 409 soap_destroy(soap);
- 410 soap_end(soap);
- 411
- 412 soap_done(soap);
- 413 soap_free(soap);
- 414
- 415 lsoap.pop();
- 416 }
- 417 }