/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include /** * keep information about the listener for a given transport */ typedef struct axis2_transport_listener_state { int waiting_calls; axis2_transport_receiver_t *listener; } axis2_transport_listener_state_t; struct axis2_listener_manager { /** hash map of listeners */ axis2_transport_listener_state_t *listener_map[AXIS2_TRANSPORT_ENUM_MAX]; axutil_thread_t *listener_thread[AXIS2_TRANSPORT_ENUM_MAX]; /** configuration context */ axis2_conf_ctx_t *conf_ctx; }; typedef struct axis2_listener_manager_worker_func_args { const axutil_env_t *env; axis2_listener_manager_t *listner_manager; axis2_transport_receiver_t *listener; } axis2_listener_manager_worker_func_args_t; void *AXIS2_THREAD_FUNC axis2_listener_manager_worker_func( axutil_thread_t * thd, void *data); AXIS2_EXTERN axis2_listener_manager_t *AXIS2_CALL axis2_listener_manager_create( const axutil_env_t * env) { axis2_listener_manager_t *listener_manager = NULL; int i = 0; AXIS2_ENV_CHECK(env, NULL); listener_manager = AXIS2_MALLOC(env->allocator, sizeof(axis2_listener_manager_t)); if(!listener_manager) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create listener manager."); return NULL; } listener_manager->conf_ctx = NULL; for(i = 0; i < AXIS2_TRANSPORT_ENUM_MAX; i++) { listener_manager->listener_map[i] = NULL; listener_manager->listener_thread[i] = NULL; } return listener_manager; } AXIS2_EXTERN axis2_status_t AXIS2_CALL axis2_listener_manager_make_sure_started( axis2_listener_manager_t * listener_manager, const axutil_env_t * env, const AXIS2_TRANSPORT_ENUMS transport, axis2_conf_ctx_t * conf_ctx) { axis2_transport_listener_state_t *tl_state = NULL; AXIS2_PARAM_CHECK(env->error, conf_ctx, AXIS2_FAILURE); if(listener_manager->conf_ctx) { if(conf_ctx != listener_manager->conf_ctx) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_CLIENT_SIDE_SUPPORT_ONLY_ONE_CONF_CTX, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Only one configuration context is supported at client side."); return AXIS2_FAILURE; } } else { listener_manager->conf_ctx = conf_ctx; } tl_state = listener_manager->listener_map[transport]; if(!tl_state) { /*means this transport not yet started, start the transport */ axis2_transport_in_desc_t *transport_in = NULL; axis2_conf_t *conf = NULL; axis2_transport_receiver_t *listener = NULL; conf = axis2_conf_ctx_get_conf(conf_ctx, env); if(conf) { transport_in = axis2_conf_get_transport_in(conf, env, transport); if(transport_in) { listener = axis2_transport_in_desc_get_recv(transport_in, env); if(listener) { #ifdef AXIS2_SVR_MULTI_THREADED axutil_thread_t *worker_thread = NULL; #endif axis2_listener_manager_worker_func_args_t *arg_list = NULL; arg_list = AXIS2_MALLOC(env->allocator, sizeof(axis2_listener_manager_worker_func_args_t)); if(!arg_list) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create listener manager worker function arguments."); return AXIS2_FAILURE; } arg_list->env = env; arg_list->listner_manager = listener_manager; arg_list->listener = listener; #ifdef AXIS2_SVR_MULTI_THREADED if (env->thread_pool) { worker_thread = axutil_thread_pool_get_thread(env->thread_pool, axis2_listener_manager_worker_func, (void *) arg_list); if (!worker_thread) { AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Thread creation failed" "Invoke non blocking failed"); } else { /*axutil_thread_pool_thread_detach(env->thread_pool, worker_thread);*/ /* we should not detach this, because, in the dual channel case we should be able to terminate the thread before deleting the listener */ } } else { AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Thread pool not set in environment." " Cannot invoke call non blocking"); } #else AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Threading not enabled." " Cannot start separate listener"); return AXIS2_FAILURE; #endif tl_state = AXIS2_MALLOC(env->allocator, sizeof(axis2_transport_listener_state_t)); if(!tl_state) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create transport listener state."); } else { tl_state->listener = listener; tl_state->waiting_calls = 0; listener_manager->listener_map[transport] = tl_state; #ifdef AXIS2_SVR_MULTI_THREADED listener_manager->listener_thread[transport] = worker_thread; #endif } } } } } if(tl_state) { tl_state->waiting_calls++; return AXIS2_SUCCESS; } else return AXIS2_FAILURE; } AXIS2_EXTERN axis2_status_t AXIS2_CALL axis2_listener_manager_stop( axis2_listener_manager_t * listener_manager, const axutil_env_t * env, const AXIS2_TRANSPORT_ENUMS transport) { axis2_transport_listener_state_t *tl_state = NULL; axis2_status_t status = AXIS2_FAILURE; axutil_thread_t *listener_thread = NULL; tl_state = listener_manager->listener_map[transport]; listener_thread = listener_manager->listener_thread[transport]; if(tl_state) { tl_state->waiting_calls--; if(tl_state->waiting_calls == 0) { status = axis2_transport_receiver_stop(tl_state->listener, env); if(status == AXIS2_SUCCESS) listener_manager->listener_map[transport] = NULL; } } if(listener_thread) { axutil_thread_pool_exit_thread(env->thread_pool, listener_thread); listener_manager->listener_thread[transport] = NULL; } return status; } AXIS2_EXTERN axis2_endpoint_ref_t *AXIS2_CALL axis2_listener_manager_get_reply_to_epr( const axis2_listener_manager_t * listener_manager, const axutil_env_t * env, const axis2_char_t * svc_name, const AXIS2_TRANSPORT_ENUMS transport) { axis2_transport_listener_state_t *tl_state = NULL; tl_state = listener_manager->listener_map[transport]; if(tl_state) { return axis2_transport_receiver_get_reply_to_epr(tl_state->listener, env, svc_name); } return NULL; } AXIS2_EXTERN void AXIS2_CALL axis2_listener_manager_free( axis2_listener_manager_t * listener_manager, const axutil_env_t * env) { int i = 0; for(i = 0; i < AXIS2_TRANSPORT_ENUM_MAX; i++) { if(listener_manager->listener_map[i]) AXIS2_FREE(env->allocator, listener_manager->listener_map[i]); } AXIS2_FREE(env->allocator, listener_manager); } AXIS2_EXTERN axis2_conf_ctx_t *AXIS2_CALL axis2_listener_manager_get_conf_ctx( const axis2_listener_manager_t * listener_manager, const axutil_env_t * env) { return listener_manager->conf_ctx; } void *AXIS2_THREAD_FUNC axis2_listener_manager_worker_func( axutil_thread_t * thd, void *data) { axis2_listener_manager_worker_func_args_t *args_list = NULL; const axutil_env_t *th_env = NULL; args_list = (axis2_listener_manager_worker_func_args_t *)data; if(!args_list) return NULL; th_env = axutil_init_thread_env(args_list->env); /* Start the protocol server. For examlle if protocol is http axis2_http_server_start function * of the axis2_http_receiver is called. */ if(args_list->listener) { axis2_transport_receiver_start(args_list->listener, th_env); } return NULL; }