Author: pnoltes
Date: Fri Dec  7 13:00:54 2012
New Revision: 1418294

URL: http://svn.apache.org/viewvc?rev=1418294&view=rev
Log:
CELIX-44: Remote Shell implementation

Added:
    incubator/celix/trunk/remote_shell/
    incubator/celix/trunk/remote_shell/CMakeLists.txt   (with props)
    incubator/celix/trunk/remote_shell/deploy.cmake
    incubator/celix/trunk/remote_shell/private/
    incubator/celix/trunk/remote_shell/private/include/
    incubator/celix/trunk/remote_shell/private/include/connection_listener.h   
(with props)
    incubator/celix/trunk/remote_shell/private/include/remote_shell.h   (with 
props)
    incubator/celix/trunk/remote_shell/private/include/shell_mediator.h   (with 
props)
    incubator/celix/trunk/remote_shell/private/src/
    incubator/celix/trunk/remote_shell/private/src/activator.c   (with props)
    incubator/celix/trunk/remote_shell/private/src/connection_listener.c   
(with props)
    incubator/celix/trunk/remote_shell/private/src/remote_shell.c   (with props)
    incubator/celix/trunk/remote_shell/private/src/shell_mediator.c   (with 
props)
Modified:
    incubator/celix/trunk/   (props changed)
    incubator/celix/trunk/CMakeLists.txt
    incubator/celix/trunk/framework/public/include/celix_errno.h
    incubator/celix/trunk/framework/public/include/framework_exports.h

Propchange: incubator/celix/trunk/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Dec  7 13:00:54 2012
@@ -0,0 +1 @@
+.project

Modified: incubator/celix/trunk/CMakeLists.txt
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/CMakeLists.txt?rev=1418294&r1=1418293&r2=1418294&view=diff
==============================================================================
--- incubator/celix/trunk/CMakeLists.txt (original)
+++ incubator/celix/trunk/CMakeLists.txt Fri Dec  7 13:00:54 2012
@@ -44,6 +44,7 @@ add_subdirectory(deployment_admin)
 add_subdirectory(remote_services)
 add_subdirectory(shell_tui)
 add_subdirectory(shell)
+add_subdirectory(remote_shell)
 add_subdirectory(log_writer)
 add_subdirectory(log_service)
 

Modified: incubator/celix/trunk/framework/public/include/celix_errno.h
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/celix_errno.h?rev=1418294&r1=1418293&r2=1418294&view=diff
==============================================================================
--- incubator/celix/trunk/framework/public/include/celix_errno.h (original)
+++ incubator/celix/trunk/framework/public/include/celix_errno.h Fri Dec  7 
13:00:54 2012
@@ -36,6 +36,12 @@
 #include "framework_exports.h"
 
 /*!
+ * Helper macro which check the current status and executes the provided 
expression if the
+ * status is still CELIX_SUCESS (0)
+ */
+#define CELIX_DO_IF(status, expr) ((status) == CELIX_SUCCESS) ? (expr) : 
(status)
+
+/*!
  * \defgroup celix_errno Error Codes
  * \ingroup framework
  * \{

Modified: incubator/celix/trunk/framework/public/include/framework_exports.h
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/framework_exports.h?rev=1418294&r1=1418293&r2=1418294&view=diff
==============================================================================
--- incubator/celix/trunk/framework/public/include/framework_exports.h 
(original)
+++ incubator/celix/trunk/framework/public/include/framework_exports.h Fri Dec  
7 13:00:54 2012
@@ -41,4 +41,4 @@ building a DLL on windows.
 #define FRAMEWORK_EXPORT __attribute__((visibility("default")))
 #endif
 
-#endif /* FRAMEWORK_EXPORTS_H_ */
\ No newline at end of file
+#endif /* FRAMEWORK_EXPORTS_H_ */

Added: incubator/celix/trunk/remote_shell/CMakeLists.txt
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/CMakeLists.txt?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/CMakeLists.txt (added)
+++ incubator/celix/trunk/remote_shell/CMakeLists.txt Fri Dec  7 13:00:54 2012
@@ -0,0 +1,43 @@
+# 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.
+celix_subproject(REMOTE_SHELL "Option to enable building the Remote Shell 
bundles" OFF DEPS LAUNCHER SHELL)
+if (REMOTE_SHELL)
+
+       SET_HEADER(BUNDLE_SYMBOLICNAME "apache_celix_remote_shell")
+       SET_HEADERS("Bundle-Name: Apache Celix Remote Shell") 
+       
+
+    bundle(remote_shell SOURCES 
+       private/src/activator 
+       private/src/connection_listener 
+       private/src/shell_mediator 
+       private/src/remote_shell
+       )
+    
+ 
+    include_directories("private/include")
+    include_directories("${PROJECT_SOURCE_DIR}/utils/public/include")
+    include_directories("${PROJECT_SOURCE_DIR}/shell/public/include")
+    
+    target_link_libraries(remote_shell celix_framework apr-1 aprutil-1)
+    
+    package(remote_shell)
+    
+    #INSTALL(FILES ${PROJECT_BINARY_DIR}/bundles/remote_shell.zip DESTINATION 
share/celix/bundles COMPONENT framework)
+    
+    #deploy("remote_shell" BUNDLES shell remote_shell shell_tui log_service)
+endif (REMOTE_SHELL)
\ No newline at end of file

Propchange: incubator/celix/trunk/remote_shell/CMakeLists.txt
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/celix/trunk/remote_shell/deploy.cmake
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/deploy.cmake?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/deploy.cmake (added)
+++ incubator/celix/trunk/remote_shell/deploy.cmake Fri Dec  7 13:00:54 2012
@@ -0,0 +1,20 @@
+# 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.
+is_enabled(REMOTE_SHELL)
+if (REMOTE_SHELL)
+       deploy("remote_shell" BUNDLES shell remote_shell shell_tui log_service)
+endif (REMOTE_SHELL)
\ No newline at end of file

Added: incubator/celix/trunk/remote_shell/private/include/connection_listener.h
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/private/include/connection_listener.h?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/private/include/connection_listener.h 
(added)
+++ incubator/celix/trunk/remote_shell/private/include/connection_listener.h 
Fri Dec  7 13:00:54 2012
@@ -0,0 +1,46 @@
+/**
+ *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.
+ */
+/*
+ * connection_listener.h
+ *
+ *  \date       Nov 4, 2012
+ *  \author            <a href="mailto:[email protected]";>Apache 
Celix Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+#ifndef connectionListener_H_
+#define connectionListener_H_
+
+#include "remote_shell.h"
+
+#include <apr_pools.h>
+
+#include <bundle_context.h>
+#include <celix_errno.h>
+
+
+
+typedef struct connection_listener *connection_listener_t;
+
+celix_status_t connectionListener_create(apr_pool_t *pool, remote_shell_t 
remoteShell, apr_int64_t port, connection_listener_t *instance);
+
+celix_status_t connectionListener_start(connection_listener_t instance);
+celix_status_t connectionListener_stop(connection_listener_t instance);
+
+#endif /* connectionListener_H_ */

Propchange: 
incubator/celix/trunk/remote_shell/private/include/connection_listener.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/celix/trunk/remote_shell/private/include/remote_shell.h
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/private/include/remote_shell.h?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/private/include/remote_shell.h (added)
+++ incubator/celix/trunk/remote_shell/private/include/remote_shell.h Fri Dec  
7 13:00:54 2012
@@ -0,0 +1,46 @@
+/**
+ *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.
+ */
+/*
+ * remote_shell.h
+ *
+ *  \date       Nov 4, 2012
+ *  \author            <a href="mailto:[email protected]";>Apache 
Celix Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_SHELL_H_
+#define REMOTE_SHELL_H_
+
+#include "shell_mediator.h"
+
+#include <apr_pools.h>
+
+#include <bundle_context.h>
+#include <celix_errno.h>
+
+
+typedef struct remote_shell *remote_shell_t;
+
+celix_status_t remoteShell_create(apr_pool_t *pool, shell_mediator_t mediator, 
apr_int64_t maximumConnections, remote_shell_t *instance);
+
+celix_status_t remoteShell_addConnection(remote_shell_t instance, apr_socket_t 
*socket);
+
+celix_status_t remoteShell_stopConnections(remote_shell_t instance);
+
+#endif /* REMOTE_SHELL_H_ */

Propchange: incubator/celix/trunk/remote_shell/private/include/remote_shell.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/celix/trunk/remote_shell/private/include/shell_mediator.h
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/private/include/shell_mediator.h?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/private/include/shell_mediator.h (added)
+++ incubator/celix/trunk/remote_shell/private/include/shell_mediator.h Fri Dec 
 7 13:00:54 2012
@@ -0,0 +1,43 @@
+/**
+ *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.
+ */
+/*
+ * shell_mediator.h
+ *
+ *  \date       Nov 4, 2012
+ *  \author            <a href="mailto:[email protected]";>Apache 
Celix Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+
+#ifndef shellMediator_H_
+#define shellMediator_H_
+
+#include <apr_pools.h>
+
+#include <bundle_context.h>
+#include <celix_errno.h>
+
+
+typedef struct shell_mediator *shell_mediator_t;
+
+celix_status_t shellMediator_create(apr_pool_t *pool, bundle_context_t 
context, shell_mediator_t *instance);
+
+celix_status_t shellMediator_executeCommand(shell_mediator_t instance, char 
*command, apr_socket_t *socket);
+
+#endif /* shellMediator_H_ */

Propchange: incubator/celix/trunk/remote_shell/private/include/shell_mediator.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/celix/trunk/remote_shell/private/src/activator.c
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/private/src/activator.c?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/private/src/activator.c (added)
+++ incubator/celix/trunk/remote_shell/private/src/activator.c Fri Dec  7 
13:00:54 2012
@@ -0,0 +1,130 @@
+/**
+ *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.
+ */
+/*
+ * activator.c
+ *
+ *  \date       Nov 4, 2012
+ *  \author            <a href="mailto:[email protected]";>Apache 
Celix Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+#include <celix_errno.h>
+
+#include <stdlib.h>
+#include <apr_strings.h>
+
+#include "bundle_activator.h"
+#include "bundle_context.h"
+
+#include "connection_listener.h"
+#include "shell_mediator.h"
+#include "remote_shell.h"
+
+#define REMOTE_SHELL_TELNET_PORT_PROPERTY_NAME ("remote.shell.telnet.port")
+#define DEFAULT_REMOTE_SHELL_TELNET_PORT (6666)
+
+#define REMOTE_SHELL_TELNET_MAXCONN_PROPERTY_NAME 
("remote.shell.telnet.maxconn")
+#define DEFAULT_REMOTE_SHELL_TELNET_MAXCONN (2)
+
+struct bundle_instance {
+       apr_pool_t *pool;
+       shell_mediator_t shellMediator;
+       remote_shell_t remoteShell;
+       connection_listener_t connectionListener;
+};
+
+typedef struct bundle_instance *bundle_instance_t;
+
+static apr_int64_t bundleActivator_getPort(bundle_context_t context);
+static apr_int64_t bundleActivator_getMaximumConnections(bundle_context_t 
context);
+static apr_int64_t bundleActivator_getProperty(bundle_context_t context, char 
* propertyName, apr_int64_t defaultValue);
+
+celix_status_t bundleActivator_create(bundle_context_t context, void 
**userData) {
+       celix_status_t status = CELIX_SUCCESS;
+    apr_pool_t *pool;
+    status = bundleContext_getMemoryPool(context, &pool);
+    if (status == CELIX_SUCCESS) {
+       bundle_instance_t bi = apr_palloc(pool, sizeof(struct bundle_instance));
+        if (userData != NULL) {
+               bi->pool = pool;
+               bi->shellMediator = NULL;
+               bi->remoteShell = NULL;
+               bi->connectionListener = NULL;
+               (*userData) = bi;
+        } else {
+               status = CELIX_ENOMEM;
+        }
+    }
+    return status;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_t 
context) {
+    celix_status_t status = CELIX_SUCCESS;
+    bundle_instance_t bi = (bundle_instance_t)userData;
+
+    apr_int64_t port = bundleActivator_getPort(context);
+    apr_int64_t maxConn = bundleActivator_getMaximumConnections(context);
+
+    status = shellMediator_create(bi->pool, context, &bi->shellMediator);
+       status = CELIX_DO_IF(status, remoteShell_create(bi->pool, 
bi->shellMediator,  maxConn, &bi->remoteShell));
+       status = CELIX_DO_IF(status, connectionListener_create(bi->pool, 
bi->remoteShell, port, &bi->connectionListener));
+    status = CELIX_DO_IF(status, 
connectionListener_start(bi->connectionListener));
+
+    return status;
+}
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_t context) 
{
+    celix_status_t status = CELIX_SUCCESS;
+    bundle_instance_t bi = (bundle_instance_t)userData;
+
+    connectionListener_stop(bi->connectionListener);
+    remoteShell_stopConnections(bi->remoteShell);
+
+    return status;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_t 
context) {
+    return CELIX_SUCCESS;
+}
+
+static apr_int64_t bundleActivator_getPort(bundle_context_t context) {
+       return bundleActivator_getProperty(context, 
REMOTE_SHELL_TELNET_PORT_PROPERTY_NAME, DEFAULT_REMOTE_SHELL_TELNET_PORT);
+}
+
+static apr_int64_t bundleActivator_getMaximumConnections(bundle_context_t 
context) {
+       return bundleActivator_getProperty(context, 
REMOTE_SHELL_TELNET_MAXCONN_PROPERTY_NAME, DEFAULT_REMOTE_SHELL_TELNET_MAXCONN);
+}
+
+static apr_int64_t bundleActivator_getProperty(bundle_context_t context, char 
* propertyName, apr_int64_t defaultValue) {
+       apr_int64_t value;
+       char *strValue = NULL;
+
+       bundleContext_getProperty(context, propertyName, &strValue);
+       if (strValue != NULL) {
+               value = apr_strtoi64(strValue, (char **)NULL, 10);
+               if (errno != 0) {
+                       printf("incorrect format for %s\n", propertyName);
+                       value = defaultValue;
+               }
+       } else {
+               value = defaultValue;
+       }
+
+       return value;
+}

Propchange: incubator/celix/trunk/remote_shell/private/src/activator.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/celix/trunk/remote_shell/private/src/connection_listener.c
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/private/src/connection_listener.c?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/private/src/connection_listener.c (added)
+++ incubator/celix/trunk/remote_shell/private/src/connection_listener.c Fri 
Dec  7 13:00:54 2012
@@ -0,0 +1,196 @@
+/**
+ *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.
+ */
+/*
+ * connection_listener.c
+ *
+ *  \date       Nov 4, 2012
+ *  \author            <a href="mailto:[email protected]";>Apache 
Celix Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+
+#include "connection_listener.h"
+
+#include "shell_mediator.h"
+#include "remote_shell.h"
+
+#include <celix_errno.h>
+
+#include <apr_pools.h>
+#include <apr_thread_mutex.h>
+#include <apr_thread_proc.h>
+#include <apr_time.h>
+#include <apr_poll.h>
+#include <apr_thread_pool.h>
+
+struct connection_listener {
+       //constant
+    apr_pool_t *pool;
+    apr_int64_t port;
+    remote_shell_t remoteShell;
+       apr_thread_mutex_t *mutex;
+
+       //protected by mutex
+       apr_thread_t *thread;
+       apr_pollset_t *pollset;
+};
+
+static void* APR_THREAD_FUNC connection_listener_thread(apr_thread_t *thread, 
void *data);
+static apr_status_t connectionListener_cleanup(connection_listener_t instance);
+
+celix_status_t connectionListener_create(apr_pool_t *pool, remote_shell_t 
remoteShell, apr_int64_t port, connection_listener_t *instance) {
+       celix_status_t status = CELIX_SUCCESS;
+    (*instance) = apr_palloc(pool, sizeof(**instance));
+    if ((*instance) != NULL) {
+       (*instance)->pool=pool;
+       (*instance)->port=port;
+               (*instance)->mutex=NULL;
+               (*instance)->remoteShell=remoteShell;
+               (*instance)->thread=NULL;
+               (*instance)->pollset=NULL;
+               apr_pool_pre_cleanup_register(pool, (*instance), (void 
*)connectionListener_cleanup);
+
+               status = apr_thread_mutex_create(&(*instance)->mutex, 
APR_THREAD_MUTEX_DEFAULT, pool);
+       } else {
+               status = CELIX_ENOMEM;
+       }
+       return status;
+}
+
+celix_status_t connectionListener_start(connection_listener_t instance) {
+       celix_status_t status = CELIX_SUCCESS;
+       apr_thread_mutex_lock(instance->mutex);
+
+       if (instance->thread == NULL) {
+               apr_threadattr_t *threadAttributes = NULL;
+               apr_threadattr_create(&threadAttributes, instance->pool);
+               apr_thread_create(&instance->thread, threadAttributes, 
connection_listener_thread, instance, instance->pool);
+       } else {
+               status = CELIX_ILLEGAL_STATE;
+       }
+
+       apr_thread_mutex_unlock(instance->mutex);
+       return status;
+}
+
+celix_status_t connectionListener_stop(connection_listener_t instance) {
+       celix_status_t status = CELIX_SUCCESS;
+       printf("CONNECTION_LISTENER: Stopping thread\n");
+       apr_thread_t *thread;
+       apr_pollset_t *pollset;
+
+       apr_thread_mutex_lock(instance->mutex);
+       thread=instance->thread;
+       instance->thread = NULL;
+       pollset=instance->pollset;
+       apr_thread_mutex_unlock(instance->mutex);
+
+       if (thread != NULL && pollset != NULL) {
+               printf("Stopping thread by waking poll on listen socket\n");
+               apr_pollset_wakeup(pollset);
+
+               apr_status_t threadStatus;
+               apr_thread_join(&threadStatus, thread);
+               printf("Done joining thread\n");
+       } else if (thread != NULL) {
+               printf("Cannot stop thread\n");
+       } else {
+               printf("No running thread\n");
+       }
+
+       return status;
+}
+
+static void* APR_THREAD_FUNC connection_listener_thread(apr_thread_t *thread, 
void *data)
+{
+       apr_status_t status = APR_SUCCESS;
+       connection_listener_t instance = data;
+
+       apr_sockaddr_t *listenAddress = NULL;
+       apr_socket_t *listenSocket = NULL;
+       apr_socket_t *acceptedSocket = NULL;
+       apr_pollset_t *pollset = NULL;
+       apr_pollfd_t pfd = { instance->pool, APR_POLL_SOCKET, APR_POLLIN, 0, { 
NULL }, NULL };
+       apr_int32_t num;
+       const apr_pollfd_t *ret_pfd;
+
+       status = apr_sockaddr_info_get(&listenAddress, NULL, APR_UNSPEC, 
instance->port, 0, instance->pool);
+       status = CELIX_DO_IF(status, apr_socket_create(&listenSocket, APR_INET, 
SOCK_STREAM, APR_PROTO_TCP, instance->pool));
+       status = CELIX_DO_IF(status, apr_socket_opt_set(listenSocket, 
APR_SO_REUSEADDR, TRUE));
+       status = CELIX_DO_IF(status, apr_socket_bind(listenSocket, 
listenAddress));
+       status = CELIX_DO_IF(status, apr_socket_listen(listenSocket, 2));
+       status = CELIX_DO_IF(status, apr_pollset_create(&pollset, 1, 
instance->pool, APR_POLLSET_WAKEABLE));
+       pfd.desc.s = listenSocket;
+       status = CELIX_DO_IF(status, apr_pollset_add(pollset, &pfd));
+
+
+    apr_thread_mutex_lock(instance->mutex);
+    instance->pollset=pollset;
+    apr_thread_mutex_unlock(instance->mutex);
+
+    if (status != CELIX_SUCCESS) {
+       char error[64];
+               apr_strerror(status, error, 64);
+       printf("Error creating and listing on socket: %s\n", error);
+    } else {
+       printf("Remote Shell accepting connections on port %i\n", 
instance->port);
+    }
+
+       while (status == CELIX_SUCCESS) {
+               status = apr_pollset_poll(pollset, -1, &num, &ret_pfd); 
//blocks on fd till a connection is made
+               if (status == APR_SUCCESS) {
+                       acceptedSocket = NULL;
+                       apr_pool_t *socketPool = NULL;
+                       apr_pool_create(&socketPool, NULL);
+                       apr_status_t socketStatus = 
apr_socket_accept(&acceptedSocket, listenSocket, socketPool);
+                       printf("REMOTE_SHELL: created connection socket\n");
+                       if (socketStatus == APR_SUCCESS) {
+                               
remoteShell_addConnection(instance->remoteShell, acceptedSocket);
+                       } else {
+                               apr_pool_destroy(socketPool);
+                               printf("Could not accept connection\n");
+                       }
+               } else if (status == APR_EINTR) {
+                       printf("Poll interrupted\n");
+               } else /*error*/ {
+                       char error[64];
+                       apr_strerror(status, error, 64);
+                       printf("Got error %s\n", error);
+                       break;
+               }
+       }
+
+       if (pollset != NULL) {
+               apr_pollset_remove(pollset, &pfd);
+               apr_pollset_destroy(pollset);
+       }
+       if (listenSocket != NULL) {
+               apr_socket_shutdown(listenSocket, APR_SHUTDOWN_READWRITE);
+               apr_socket_close(listenSocket);
+       }
+
+    apr_thread_exit(thread, status);
+    return NULL;
+}
+
+static apr_status_t connectionListener_cleanup(connection_listener_t instance) 
{
+        celix_status_t status = CELIX_SUCCESS;
+        status = connectionListener_stop(instance);
+        return APR_SUCCESS;
+}

Propchange: incubator/celix/trunk/remote_shell/private/src/connection_listener.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/celix/trunk/remote_shell/private/src/remote_shell.c
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/private/src/remote_shell.c?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/private/src/remote_shell.c (added)
+++ incubator/celix/trunk/remote_shell/private/src/remote_shell.c Fri Dec  7 
13:00:54 2012
@@ -0,0 +1,243 @@
+/**
+ *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.
+ */
+/*
+ * remote_shell.c
+ *
+ *  \date       Nov 4, 2012
+ *  \author            <a href="mailto:[email protected]";>Apache 
Celix Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+
+#include "remote_shell.h"
+
+#include <stdlib.h>
+
+#include <apr_pools.h>
+#include <apr_thread_mutex.h>
+#include <apr_thread_pool.h>
+#include <apr_strings.h>
+#include <apr_poll.h>
+
+#include <utils.h>
+#include <array_list.h>
+
+#define COMMAND_BUFF_SIZE (256)
+
+#define PROMPT ("-> ")
+#define WELCOME ("\n---- Apache Celix Remote Shell ----\n---- Type exit to 
disconnect   ----\n\n-> ")
+#define GOODBYE ("Goobye!\n")
+#define ERROR ("Error executing command!\n")
+#define MAXIMUM_CONNECTIONS_REACHED ("Maximum number of connections  reached. 
Disconnecting ...\n")
+
+struct remote_shell {
+       apr_pool_t *pool;
+       shell_mediator_t mediator;
+       apr_thread_mutex_t *mutex;
+       apr_int64_t maximumConnections;
+
+       //protected by mutex
+       apr_thread_pool_t *threadPool;
+       array_list_t connections;
+};
+
+struct connection {
+       remote_shell_t parent;
+       apr_socket_t *socket;
+       apr_pool_t *pool;
+       apr_pollset_t *pollset;
+};
+
+typedef struct connection *connection_t;
+
+static apr_status_t remoteShell_cleanup(remote_shell_t instance); //gets 
called from apr pool cleanup
+
+static celix_status_t remoteShell_connection_print(connection_t connection, 
char * text);
+static celix_status_t remoteShell_connection_execute(connection_t connection, 
char *command);
+static void* remoteShell_connection_run(apr_thread_t *thread, void *data);
+
+celix_status_t remoteShell_create(apr_pool_t *pool, shell_mediator_t mediator, 
apr_int64_t maximumConnections, remote_shell_t *instance) {
+       celix_status_t status = CELIX_SUCCESS;
+       (*instance) = apr_palloc(pool, sizeof(**instance));
+       if ((*instance) != NULL) {
+               (*instance)->pool = pool;
+               (*instance)->mediator = mediator;
+               (*instance)->maximumConnections=maximumConnections;
+               (*instance)->threadPool = NULL;
+               (*instance)->mutex = NULL;
+               (*instance)->connections = NULL;
+
+               apr_pool_pre_cleanup_register(pool, (*instance), (void 
*)remoteShell_cleanup);
+
+               status = apr_thread_mutex_create(&(*instance)->mutex, 
APR_THREAD_MUTEX_DEFAULT, pool);
+               status = apr_thread_pool_create(&(*instance)->threadPool, 0, 
maximumConnections, pool);
+               status = arrayList_create(pool, &(*instance)->connections);
+       } else {
+               status = CELIX_ENOMEM;
+       }
+       return status;
+}
+
+static apr_status_t remoteShell_cleanup(remote_shell_t instance) {
+       remoteShell_stopConnections(instance);
+
+       apr_thread_mutex_lock(instance->mutex);
+       arrayList_destroy(instance->connections);
+       apr_thread_mutex_unlock(instance->mutex);
+
+       return APR_SUCCESS;
+}
+
+celix_status_t remoteShell_addConnection(remote_shell_t instance, apr_socket_t 
*socket) {
+       celix_status_t status = CELIX_SUCCESS;
+       apr_pool_t *pool = apr_socket_pool_get(socket);
+       connection_t connection = apr_palloc(pool, sizeof(struct connection));
+       if (connection != NULL) {
+               connection->parent = instance;
+               connection->socket = socket;
+               connection->pool = pool;
+               connection->pollset = NULL;
+
+               apr_pollset_create(&connection->pollset, 1, connection->pool, 
APR_POLLSET_WAKEABLE);
+               apr_thread_mutex_lock(instance->mutex);
+               if (apr_thread_pool_busy_count(instance->threadPool) < 
instance->maximumConnections) {
+                       arrayList_add(instance->connections, connection);
+                       status = apr_thread_pool_push(instance->threadPool, 
remoteShell_connection_run, connection, 0, instance);
+               } else {
+                       status = APR_ECONNREFUSED;
+                       remoteShell_connection_print(connection, 
MAXIMUM_CONNECTIONS_REACHED);
+               }
+               apr_thread_mutex_unlock(instance->mutex);
+       } else {
+               status = CELIX_ENOMEM;
+       }
+
+       if (status != CELIX_SUCCESS) {
+               apr_socket_close(socket);
+               apr_pool_destroy(pool);
+       }
+       return status;
+}
+
+celix_status_t remoteShell_stopConnections(remote_shell_t instance) {
+       celix_status_t status = CELIX_SUCCESS;
+
+       apr_thread_mutex_lock(instance->mutex);
+       int length = arrayList_size(instance->connections);
+       for (int i = 0; i < length; i += 1) {
+               connection_t connection = arrayList_get(instance->connections, 
i);
+               apr_pollset_wakeup(connection->pollset);
+       }
+       apr_thread_mutex_unlock(instance->mutex);
+       apr_thread_pool_tasks_cancel(instance->threadPool,instance);
+
+
+       return status;
+}
+
+void * remoteShell_connection_run(apr_thread_t *thread, void *data) {
+       celix_status_t status = CELIX_SUCCESS;
+       connection_t connection = data;
+
+       apr_size_t len;
+       char buff[COMMAND_BUFF_SIZE];
+       apr_pollfd_t pfd = { connection->pool, APR_POLL_SOCKET, APR_POLLIN, 0, 
{ NULL }, NULL };
+       pfd.desc.s = connection->socket;
+       apr_int32_t num;
+       const apr_pollfd_t *ret_pfd;
+
+       status = CELIX_DO_IF(status, apr_pollset_add(connection->pollset, 
&pfd));
+
+       remoteShell_connection_print(connection, WELCOME);
+       while (status == CELIX_SUCCESS) {
+               status = apr_pollset_poll(connection->pollset, -1, &num, 
&ret_pfd); //blocks on fd until a connection is made
+               if (status == APR_SUCCESS) {
+                       len = COMMAND_BUFF_SIZE -1;
+                       status = apr_socket_recv(connection->socket, buff, 
&len);
+                       if (status == APR_SUCCESS && len < COMMAND_BUFF_SIZE) {
+                               buff[len]='\0';
+                               apr_status_t commandStatus = 
remoteShell_connection_execute(connection, buff);
+                               if (commandStatus == CELIX_SUCCESS) {
+                                       
remoteShell_connection_print(connection, PROMPT);
+                               } else if (commandStatus == APR_EOF) {
+                                       //exit command
+                                       break;
+                               } else { //error
+                                       
remoteShell_connection_print(connection, ERROR);
+                                       
remoteShell_connection_print(connection, PROMPT);
+                               }
+
+                       } else {
+                               char error[64];
+                               apr_strerror(status, error, 64);
+                               printf("Got error %s\n", error);
+                       }
+               } else if (status == APR_EINTR) {
+                       printf("Poll interrupted\n");
+               } else /*error*/ {
+                       char error[64];
+                       apr_strerror(status, error, 64);
+                       printf("Got error %s\n", error);
+                       break;
+               }
+       }
+       remoteShell_connection_print(connection, GOODBYE);
+
+       printf("Closing socket\n");
+       apr_thread_mutex_lock(connection->parent->mutex);
+       arrayList_removeElement(connection->parent->connections, connection);
+       apr_thread_mutex_unlock(connection->parent->mutex);
+
+       apr_socket_shutdown(connection->socket, APR_SHUTDOWN_READWRITE);
+       apr_pollset_destroy(connection->pollset);
+       apr_socket_close(connection->socket);
+       apr_pool_destroy(connection->pool);
+
+       return NULL;
+}
+
+static celix_status_t remoteShell_connection_execute(connection_t connection, 
char *command) {
+       celix_status_t status;
+
+       apr_pool_t *workPool = NULL;
+       status = apr_pool_create(&workPool,  connection->pool);
+
+       if (status == CELIX_SUCCESS) {
+               char *dline = apr_pstrdup(workPool, command);
+               char *line = string_trim(dline);
+               int len = strlen(line);
+
+               if (len == 0) {
+                       //ignore
+               } else if (len == 4 && strncmp("exit", line, 4) == 0) {
+                       status = APR_EOF;
+               } else {
+                       status = 
shellMediator_executeCommand(connection->parent->mediator, line, 
connection->socket);
+               }
+
+               apr_pool_destroy(workPool);
+       }
+
+       return status;
+}
+
+celix_status_t remoteShell_connection_print(connection_t connection, char 
*text) {
+       apr_size_t len = strlen(text);
+       return apr_socket_send(connection->socket, text, &len);
+}

Propchange: incubator/celix/trunk/remote_shell/private/src/remote_shell.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/celix/trunk/remote_shell/private/src/shell_mediator.c
URL: 
http://svn.apache.org/viewvc/incubator/celix/trunk/remote_shell/private/src/shell_mediator.c?rev=1418294&view=auto
==============================================================================
--- incubator/celix/trunk/remote_shell/private/src/shell_mediator.c (added)
+++ incubator/celix/trunk/remote_shell/private/src/shell_mediator.c Fri Dec  7 
13:00:54 2012
@@ -0,0 +1,151 @@
+/**
+ *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.
+ */
+/*
+ * shell_mediator.c
+ *
+ *  \date       Nov 4, 2012
+ *  \author            <a href="mailto:[email protected]";>Apache 
Celix Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+
+#include "shell_mediator.h"
+
+#include <stdlib.h>
+
+#include <apr_pools.h>
+#include <apr_thread_mutex.h>
+
+#include <utils.h>
+#include <shell.h>
+#include <service_tracker.h>
+#include <command.h>
+
+struct shell_mediator {
+    apr_pool_t *pool;
+       bundle_context_t context;
+       service_tracker_t tracker;
+       apr_thread_mutex_t *mutex;
+
+       //protected by mutex
+       SHELL_SERVICE shellService;
+};
+
+//NOTE: multiple instances of shell_mediator are not supported, because we need
+//             a non ADT - shared between instances - variable.
+static apr_socket_t *currentOutputSocket = NULL;
+
+static apr_status_t shellMediator_cleanup(shell_mediator_t instance); //gets 
called from apr pool cleanup
+static void shellMediator_writeOnCurrentSocket(char *buff);
+
+static celix_status_t shellMediator_addingService(void *handler, 
service_reference_t reference, void **service);
+static celix_status_t shellMediator_addedService(void *handler, 
service_reference_t reference, void * service);
+static celix_status_t shellMediator_modifiedService(void *handler, 
service_reference_t reference, void * service);
+static celix_status_t shellMediator_removedService(void *handler, 
service_reference_t reference, void * service);
+
+celix_status_t shellMediator_create(apr_pool_t *pool, bundle_context_t 
context, shell_mediator_t *instance) {
+       celix_status_t status = CELIX_SUCCESS;
+       service_tracker_customizer_t customizer = NULL;
+
+    (*instance) = apr_palloc(pool, sizeof(**instance));
+    if ((*instance) != NULL) {
+       (*instance)->pool=pool;
+               (*instance)->context=context;
+               (*instance)->tracker=NULL;
+               (*instance)->mutex=NULL;
+               (*instance)->shellService=NULL;
+               apr_pool_pre_cleanup_register(pool, (*instance), (void 
*)shellMediator_cleanup);
+
+               status = apr_thread_mutex_create(&(*instance)->mutex, 
APR_THREAD_MUTEX_DEFAULT, pool);
+               status = CELIX_DO_IF(status, 
serviceTrackerCustomizer_create(pool, (*instance), shellMediator_addingService, 
shellMediator_addedService,
+                               shellMediator_modifiedService, 
shellMediator_removedService, &customizer));
+               status = CELIX_DO_IF(status, serviceTracker_create(pool, 
context, (char *)SHELL_SERVICE_NAME, customizer, &(*instance)->tracker));
+               if (status == CELIX_SUCCESS) {
+                       serviceTracker_open((*instance)->tracker);
+               }
+       } else {
+               status = CELIX_ENOMEM;
+       }
+
+    if (status != CELIX_SUCCESS) {
+       printf("Error creating shell_mediator, error code is %i\n", status);
+    }
+       return status;
+}
+
+static apr_status_t shellMediator_cleanup(shell_mediator_t instance) {
+        apr_thread_mutex_lock(instance->mutex);
+
+        instance->shellService=NULL;
+        serviceTracker_close(instance->tracker);
+
+        apr_thread_mutex_unlock(instance->mutex);
+        return APR_SUCCESS;
+}
+
+static void shellMediator_writeOnCurrentSocket(char *buff) {
+       apr_size_t len = strlen(buff);
+       apr_socket_send(currentOutputSocket, buff, &len);
+}
+
+celix_status_t shellMediator_executeCommand(shell_mediator_t instance, char 
*command, apr_socket_t *socket) {
+       apr_status_t status;
+
+       apr_thread_mutex_lock(instance->mutex);
+       if (instance->shellService != NULL) {
+               currentOutputSocket=socket;
+               
instance->shellService->executeCommand(instance->shellService->shell, command, 
shellMediator_writeOnCurrentSocket, shellMediator_writeOnCurrentSocket);
+               currentOutputSocket=NULL;
+       }
+       apr_thread_mutex_unlock(instance->mutex);
+
+       return status;
+}
+
+static celix_status_t shellMediator_addingService(void *handler, 
service_reference_t reference, void **service) {
+       celix_status_t status = CELIX_SUCCESS;
+       shell_mediator_t instance = handler;
+       bundleContext_getService(instance->context, reference, service);
+       return status;
+}
+
+static celix_status_t shellMediator_addedService(void *handler, 
service_reference_t reference, void * service) {
+       celix_status_t status = CELIX_SUCCESS;
+       shell_mediator_t instance = handler;
+       apr_thread_mutex_lock(instance->mutex);
+       instance->shellService = service;
+       apr_thread_mutex_unlock(instance->mutex);
+       return status;
+}
+
+static celix_status_t shellMediator_modifiedService(void *handler, 
service_reference_t reference, void * service) {
+       celix_status_t status = CELIX_SUCCESS;
+       //ignore
+       return status;
+}
+
+static celix_status_t shellMediator_removedService(void *handler, 
service_reference_t reference, void * service) {
+       celix_status_t status = CELIX_SUCCESS;
+       shell_mediator_t instance = handler;
+       apr_thread_mutex_lock(instance->mutex);
+       instance->shellService = NULL;
+       apr_thread_mutex_unlock(instance->mutex);
+       return status;
+}
+

Propchange: incubator/celix/trunk/remote_shell/private/src/shell_mediator.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to