extern "C" SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap) { #ifndef WITH_FASTCGI unsigned int k = soap->max_keep_alive; #endif do { #ifndef WITH_FASTCGI if (soap->max_keep_alive > 0 && !--k) soap->keep_alive = 0; #endif if (soap_begin_serve(soap)) { if (soap->error >= SOAP_STOP) continue; return soap->error; } if (soap_serve_request(soap) || (soap->fserveloop && soap->fserveloop(soap))) { #ifdef WITH_FASTCGI soap_send_fault(soap); #else return soap_send_fault(soap); #endif } #ifdef WITH_FASTCGI soap_destroy(soap); soap_end(soap); } while (1); #else } while (soap->keep_alive);
SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap* soap) { #ifndef WITH_FASTCGI unsigned int k = soap->max_keep_alive; #endif do { #ifdef WITH_FASTCGI if (FCGI_Accept() < 0) { soap->error = SOAP_EOF; return soap_send_fault(soap); } #endif soap_begin(soap); #ifndef WITH_FASTCGI if (soap->max_keep_alive > 0 && !--k) soap->keep_alive = 0; #endif if (soap_begin_recv(soap)) { if (soap->error < SOAP_STOP) { #ifdef WITH_FASTCGI soap_send_fault(soap); #else return soap_send_fault(soap); #endif } soap_closesock(soap); continue; } if (soap_envelope_begin_in(soap) || soap_recv_header(soap) || soap_body_begin_in(soap) || soap_serve_request(soap) || (soap->fserveloop && soap->fserveloop(soap))) { #ifdef WITH_FASTCGI soap_send_fault(soap); #else return soap_send_fault(soap); #endif } #ifdef WITH_FASTCGI soap_destroy(soap); soap_end(soap); } while (1); #else } while (soap->keep_alive);
int Service::start(int port) { if (!soap_valid_socket(bind(NULL, port, 100))) { soap_stream_fault(std::cerr); exit(1); } std::cerr << "Server Running" << std::endl; /* optional: set accept timeout to pulse acks every 500 ms, see below */ soap->accept_timeout = -500000; for (;;) { if (soap_valid_socket(accept())) { /* with iterative servers asynchronous messaging deadlock scenarios exist! */ /* chain the WSRM service operations after the main service operations */ if (soap_begin_serve(soap) == SOAP_OK) if (dispatch() == SOAP_NO_METHOD) soap_serve_request(soap); if (soap->error) soap_send_fault(soap); if (soap->error && soap->error != SOAP_STOP) soap_stream_fault(std::cerr); destroy(); callback.destroy(); soap_wsrm_dump(soap, stdout); } else { /* error or timeout? */ if (soap->errnum) { soap_stream_fault(std::cerr); exit(1); } /* timeout occurs after 1 sec */ /* send acks to peers (optional), 10 ms per message timeout */ soap_wsrm_pulse(soap, -10000); /* 10 ms */ } } return SOAP_OK; }
void *callback_thread(void *ctx) { WSDualHttpBinding_USCOREICalculatorDuplexService *callback = (WSDualHttpBinding_USCOREICalculatorDuplexService*)ctx; THREAD_DETACH(THREAD_ID); /* chain the WSRM operations after callback operations */ if (soap_begin_serve(callback->soap) == SOAP_OK) if (callback->dispatch() == SOAP_NO_METHOD) soap_serve_request(callback->soap); if (callback->soap->error) soap_send_fault(callback->soap); if (callback->soap->error != SOAP_STOP && callback->soap->error != SOAP_EOF) callback->soap_stream_fault(std::cerr); else if (callback->soap->error != SOAP_EOF || callback->soap->errnum) soap_wsrm_dump(callback->soap, stdout); callback->destroy(); delete callback; return NULL; }
int Client::poll(int timeout) { #ifdef CB_THREAD // We leave the acceptance of messages to the callback server thread if (timeout < 0) timeout = 1; sleep(timeout); // but we want to wait some until these messages arrive #else callback.soap->accept_timeout = timeout; printf("\n**** Callback Polling\n"); while (soap_valid_socket(callback.accept())) { /* chain the WSRM operations after callback operations */ if (soap_begin_serve(callback.soap) == SOAP_OK) if (callback.dispatch() == SOAP_NO_METHOD) soap_serve_request(callback.soap); if (callback.soap->error) soap_send_fault(callback.soap); soap->error = callback.soap->error; callback.destroy(); if (soap->error && soap->error != SOAP_STOP) { soap_stream_fault(std::cerr); return soap->error; } soap_wsrm_dump(callback.soap, stdout); } #endif return SOAP_OK; }
/***************************************************************************** 函 数 名 : ws_internal_call 功能描述 : 以内部方式调用一个web service方法 输入参数 : ws_env ---- web service执行环境 ws_req_res ---- web service参数结构 method ---- web service方法名 handle ---- web service处理函数所在so文件据柄 internal_env -- 内部执行环境 输出参数 : 无 返 回 值 : ERROR_SYSTEM 失败 ERR_SUCESS 成功,无错误 SOAP_FAULT 执行有错误,错误放soapFault中 调用函数 : 被调函数 : ============================================================================ 修改历史 : 1.日 期 : 2008年8月8日 修改内容 : 新生成函数 *****************************************************************************/ u_int32_t ws_internal_call(WS_ENV* ws_env, WS_REQ_RES* ws_req_res, char* method, void* handle, WS_INTERNAL_ENV *internal_env) { char* pchar; char* error; /* 向web service发送数据的管道 */ int file_to_ws[2]; /* 从web service接收数据的管道 */ int file_from_ws[2]; SOAP_SERVE_REQUEST *soap_serve_request; u_int32_t ret; if((NULL == ws_env) || (NULL == ws_req_res) || (NULL == method)) { return ERROR_SYSTEM; } do { /* 只执行一次 */ error = NULL; dlerror(); /* Clear any existing error */ /* 读入web service执行函数 */ soap_serve_request = dlsym(handle, "soap_serve_request"); if ((error = dlerror()) != NULL) { break; } #ifndef WITH_NOIDREF /* 读入各模块支持函数,在web_frame.so中引用 */ soap_putelement_ext = dlsym(handle, "soap_putelement"); if ((error = dlerror()) != NULL) { break; } #endif soap_ignore_element_ext = dlsym(handle, "soap_ignore_element"); if ((error = dlerror()) != NULL) { break; } soap_default_int_ext = dlsym(handle, "soap_default_int"); if ((error = dlerror()) != NULL) { break; } #ifndef WITH_NOIDREF soap_getindependent_ext = dlsym(handle, "soap_getindependent"); if ((error = dlerror()) != NULL) { break; } #endif soap_in_int_ext = dlsym(handle, "soap_in_int"); if ((error = dlerror()) != NULL) { break; } #ifndef WITH_NOIDREF soap_getelement_ext = dlsym(handle, "soap_getelement"); if ((error = dlerror()) != NULL) { break; } soap_putindependent_ext = dlsym(handle, "soap_putindependent"); if ((error = dlerror()) != NULL) { break; } #endif soap_out_int_ext = dlsym(handle, "soap_out_int"); if ((error = dlerror()) != NULL) { break; } #ifndef WITH_NOIDREF soap_markelement_ext = dlsym(handle, "soap_markelement"); if ((error = dlerror()) != NULL) { break; } #endif error = NULL; break; }while(error); if (NULL != error) { s8 err_info[200]; /* 发生错误 */ WEB_SEND_DEBUG_s(error); snprintf(err_info, sizeof(err_info), "Load web service method %s failed:%s", method, error); return (u32)ws_send_soap_error(ws_env, err_info); } /* 建立管道,准备向web service发送信息 */ (void)pipe((int *)file_to_ws); /* 建立管道,准备向从web service接收信息 */ (void)pipe((int *)file_from_ws); /* 通知web service要执行的方法,格式形如<ws:getSegmentById/> */ pchar = "<ws:"; ret = (u_int32_t)write(file_to_ws[1], pchar, strlen(pchar)); pchar = method; write(file_to_ws[1], pchar, strlen(pchar)); // pchar = "/>"; // <nop/>用于表示参数,让gsoap可以正常处理 pchar = "><nop/></ws:"; write(file_to_ws[1], pchar, strlen(pchar)); pchar = method; write(file_to_ws[1], pchar, strlen(pchar)); pchar = ">"; write(file_to_ws[1], pchar, strlen(pchar)); close(file_to_ws[1]); /* 准备执行web service */ ws_begin_exe(ws_env); /* 设置web service执行时的输入输出流 */ ws_env->recvfd = file_to_ws[0]; ws_env->sendfd = file_from_ws[1]; /* 生成内部执行环境 */ // memset(internal_env, 0, sizeof(WS_INTERNAL_ENV)); 不能清0,只能做自己的赋值 internal_env->internal_run = BOOL_TRUE; internal_env->ws_req_res = ws_req_res; /* web service执行环境挂入内部执行环境 */ ws_plug_intl_env(ws_env, internal_env); /* 执行 web service */ ret = (u_int32_t)soap_serve_request(ws_env); if (WS_OK != ret) { soap_set_fault(ws_env); ret = WS_OK; } /* 关闭web service输入流 */ close(file_from_ws[1]); close(file_from_ws[0]); close(file_to_ws[0]); ws_env->user = NULL; return ret; }
void process_requests(int server_s, struct soap *soap)/*by SeanHou*/ { /* :TODO:Monday, December 01, 2014 11:17:36 HKT:SeanHou: */ int OnvifEN = 0; int lookupindex = 0; char service_uri[100] = ""; memset((void*)&soap->peer, 0, sizeof(soap->peer)); soap->socket = SOAP_INVALID_SOCKET; soap->error = SOAP_OK; soap->errmode = 0; soap->keep_alive = 0; fprintf(stderr, "Warning:" \ "(==>%s).\n", __func__); /* :TODO:End--- */ int retval = 0; request *current, *trailer; if (pending_requests) { get_request(server_s); #ifdef ORIGINAL_BEHAVIOR pending_requests = 0; #endif } current = request_ready; while (current) { /* :TODO:Monday, December 01, 2014 11:18:42 HKT:SeanHou: juge is onvif */ OnvifEN = isonvif(current->client_stream, service_uri, &lookupindex); if(OnvifEN == 1) { fprintf(stderr, "[boa:onvif] Warning: is onvif line[%d]remote port[%d]h2ns[%d]remote ip[%s]\n", __LINE__, current->remote_port, htons(current->remote_port), current->remote_ip_addr); struct sockaddr_in onvif_client_addr; memset(&onvif_client_addr, 0, sizeof(onvif_client_addr)); onvif_client_addr.sin_family = AF_INET; onvif_client_addr.sin_port = htons(current->remote_port);//随机端口 onvif_client_addr.sin_addr.s_addr = inet_addr(current->remote_ip_addr);// soap->socket = current->fd; soap->peer = onvif_client_addr; if (soap_valid_socket(soap->socket)) { soap->ip = ntohl(soap->peer.sin_addr.s_addr); soap->port = (int)ntohs(soap->peer.sin_port); soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); } g_onvif_buffer = (char *)soap_malloc(soap, sizeof(current->client_stream)); strcpy(g_onvif_buffer, current->client_stream);//mark soap_begin_recv(soap); if (soap_envelope_begin_in(soap)) { soap_send_fault(soap); } if (soap_recv_header(soap)) { soap_send_fault(soap); } if (soap_body_begin_in(soap)) { soap_send_fault(soap); } int errorCode = 0; if (errorCode = soap_serve_request(soap)) { fprintf(stderr, "[boa:onvif]soap_serve_request fail, errorCode %d \n", errorCode); soap_send_fault(soap); } memset(current->client_stream, 0, CLIENT_STREAM_SIZE ); soap_dealloc(soap, NULL); soap_destroy(soap); soap_end(soap); current->status = DONE; close(soap->socket); continue; } /* :TODO:End--- */ time(¤t_time); if (current->buffer_end && /* there is data in the buffer */ current->status != DEAD && current->status != DONE) { retval = req_flush(current); /* * retval can be -2=error, -1=blocked, or bytes left */ if (retval == -2) { /* error */ current->status = DEAD; retval = 0; } else if (retval >= 0) { /* notice the >= which is different from below? Here, we may just be flushing headers. We don't want to return 0 because we are not DONE or DEAD */ retval = 1; } } else { switch (current->status) { case READ_HEADER: case ONE_CR: case ONE_LF: case TWO_CR: retval = read_header(current); break; case BODY_READ: retval = read_body(current); break; case BODY_WRITE: retval = write_body(current); break; case WRITE: retval = process_get(current); break; case PIPE_READ: retval = read_from_pipe(current); break; case PIPE_WRITE: retval = write_from_pipe(current); break; case DONE: /* a non-status that will terminate the request */ retval = req_flush(current); /* * retval can be -2=error, -1=blocked, or bytes left */ if (retval == -2) { /* error */ current->status = DEAD; retval = 0; } else if (retval > 0) { retval = 1; } break; case DEAD: retval = 0; current->buffer_end = 0; SQUASH_KA(current); break; default: retval = 0; fprintf(stderr, "Unknown status (%d), " "closing!\n", current->status); current->status = DEAD; break; } } if (sigterm_flag) SQUASH_KA(current); /* we put this here instead of after the switch so that * if we are on the last request, and get_request is successful, * current->next is valid! */ if (pending_requests) get_request(server_s); switch (retval) { case -1: /* request blocked */ trailer = current; current = current->next; block_request(trailer); break; case 0: /* request complete */ current->time_last = current_time; trailer = current; current = current->next; free_request(&request_ready, trailer); break; case 1: /* more to do */ current->time_last = current_time; current = current->next; break; default: log_error_time(); fprintf(stderr, "Unknown retval in process.c - " "Status: %d, retval: %d\n", current->status, retval); current = current->next; break; } } }