summaryrefslogtreecommitdiffstats
path: root/src/core/clientapi/listener_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/clientapi/listener_manager.c')
-rw-r--r--src/core/clientapi/listener_manager.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/core/clientapi/listener_manager.c b/src/core/clientapi/listener_manager.c
new file mode 100644
index 0000000..1e3e3f2
--- /dev/null
+++ b/src/core/clientapi/listener_manager.c
@@ -0,0 +1,302 @@
+/*
+ * 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 <axis2_listener_manager.h>
+#include <axis2_const.h>
+#include <axutil_hash.h>
+#include <axis2_transport_receiver.h>
+
+/**
+ * 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)
+ {
+ axutil_thread_t *worker_thread = NULL;
+ 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;
+ listener_manager->listener_thread[transport] = worker_thread;
+ }
+ }
+ }
+ }
+ }
+
+ 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;
+}