Dali remote control and monitoring 57/25057/20
authorNick Holland <nick.holland@partner.samsung.com>
Fri, 6 Feb 2015 10:52:38 +0000 (10:52 +0000)
committerNick Holland <nick.holland@partner.samsung.com>
Tue, 24 Mar 2015 09:23:48 +0000 (09:23 +0000)
No ability in Dali for remote interactive control and performance monitoring ( via network).
Usage, apply patch then $nc localhost 3031  (type help)
Or connect using Stage Hand tool.

To perform a scene dump to a JSON file ( for black box testing )
echo "dump_scene" | nc -q4 adress port  > scene.json

Change-Id: Ib43e547b931b66dde91d3f1bb011d2e7a90879fc
Signed-off-by: Nick Holland <nick.holland@partner.samsung.com>
26 files changed:
adaptors/base/environment-options.cpp
adaptors/base/environment-options.h
adaptors/base/environment-variables.h
adaptors/base/file.list
adaptors/base/interfaces/adaptor-internal-services.h
adaptors/base/interfaces/performance-interface.h
adaptors/base/interfaces/socket-factory-interface.h [new file with mode: 0644]
adaptors/base/interfaces/socket-interface.h [new file with mode: 0644]
adaptors/base/performance-logging/networking/client-send-data-interface.h [new file with mode: 0644]
adaptors/base/performance-logging/networking/event/automation.cpp [new file with mode: 0644]
adaptors/base/performance-logging/networking/event/automation.h [new file with mode: 0644]
adaptors/base/performance-logging/networking/network-performance-client.cpp [new file with mode: 0644]
adaptors/base/performance-logging/networking/network-performance-client.h [new file with mode: 0644]
adaptors/base/performance-logging/networking/network-performance-protocol.cpp [new file with mode: 0644]
adaptors/base/performance-logging/networking/network-performance-protocol.h [new file with mode: 0644]
adaptors/base/performance-logging/networking/network-performance-server.cpp [new file with mode: 0644]
adaptors/base/performance-logging/networking/network-performance-server.h [new file with mode: 0644]
adaptors/base/performance-logging/performance-server.cpp
adaptors/base/performance-logging/performance-server.h
adaptors/common/adaptor-impl.cpp
adaptors/common/adaptor-impl.h
adaptors/common/file.list
adaptors/common/networking/socket-factory.cpp [new file with mode: 0644]
adaptors/common/networking/socket-factory.h [new file with mode: 0644]
adaptors/common/networking/socket-impl.cpp [new file with mode: 0644]
adaptors/common/networking/socket-impl.h [new file with mode: 0644]

index 94ae425..118eb29 100644 (file)
@@ -32,7 +32,8 @@ namespace
 const unsigned int DEFAULT_STATISTICS_LOG_FREQUENCY = 2;
 }
 EnvironmentOptions::EnvironmentOptions()
-: mFpsFrequency(0),
+: mNetworkControl(0),
+  mFpsFrequency(0),
   mUpdateStatusFrequency(0),
   mPerformanceStatsLevel(0),
   mPerformanceStatsFrequency( DEFAULT_STATISTICS_LOG_FREQUENCY),
@@ -59,6 +60,7 @@ EnvironmentOptions::~EnvironmentOptions()
 }
 
 void EnvironmentOptions::SetLogOptions( const Dali::Integration::Log::LogFunction& logFunction,
+                             unsigned int networkControl,
                              unsigned int logFrameRateFrequency,
                              unsigned int logupdateStatusFrequency,
                              unsigned int logPerformanceStats,
@@ -67,6 +69,7 @@ void EnvironmentOptions::SetLogOptions( const Dali::Integration::Log::LogFunctio
                              unsigned int logPanGestureLevel )
 {
   mLogFunction = logFunction;
+  mNetworkControl = networkControl;
   mFpsFrequency = logFrameRateFrequency;
   mUpdateStatusFrequency = logupdateStatusFrequency;
   mPerformanceStatsLevel = logPerformanceStats;
@@ -85,6 +88,10 @@ void EnvironmentOptions::UnInstallLogFunction() const
   Dali::Integration::Log::UninstallLogFunction();
 }
 
+unsigned int EnvironmentOptions::GetNetworkControlMode() const
+{
+  return mNetworkControl;
+}
 unsigned int EnvironmentOptions::GetFrameRateLoggingFrequency() const
 {
   return mFpsFrequency;
@@ -236,7 +243,8 @@ void EnvironmentOptions::SetWindowHeight( int height )
 bool EnvironmentOptions::PerformanceServerRequired() const
 {
   return ( (GetPerformanceStatsLoggingOptions() > 0) ||
-           ( GetPerformanceTimeStampOutput() > 0 ) );
+           ( GetPerformanceTimeStampOutput() > 0 ) ||
+           ( GetNetworkControlMode() > 0) );
 }
 
 } // Adaptor
index 6c98ae1..61e692b 100644 (file)
@@ -50,6 +50,7 @@ public:
 
   /**
    * @param logFunction logging function
+   * @param networkControl whether network control is enabled
    * @param logFilterOptions bitmask of the logging options defined in intergration/debug.h (e.g.
    * @param logFrameRateFrequency frequency of how often FPS is logged out (e.g. 0 = off, 2 = every 2 seconds).
    * @param logupdateStatusFrequency frequency of how often the update status is logged in number of frames
@@ -59,6 +60,7 @@ public:
    * @param logPanGestureLevel pan-gesture logging, 0 = disabled,  1 = enabled
    */
   void SetLogOptions( const Dali::Integration::Log::LogFunction& logFunction,
+                       unsigned int networkControl,
                        unsigned int logFrameRateFrequency,
                        unsigned int logupdateStatusFrequency,
                        unsigned int logPerformanceStats,
@@ -77,6 +79,11 @@ public:
   void UnInstallLogFunction() const;
 
   /**
+   * @return whether network control is enabled or not ( 0 = off, 1 = on )
+   */
+  unsigned int GetNetworkControlMode() const;
+
+  /**
    * @return frequency of how often FPS is logged out (e.g. 0 = off, 2 = every 2 seconds).
    */
   unsigned int GetFrameRateLoggingFrequency() const;
@@ -257,6 +264,7 @@ public:
 
 private:
 
+  unsigned int mNetworkControl;                   ///< whether network control is enabled
   unsigned int mFpsFrequency;                     ///< how often fps is logged out in seconds
   unsigned int mUpdateStatusFrequency;            ///< how often update status is logged out in frames
   unsigned int mPerformanceStatsLevel;            ///< performance statistics logging bitmask
index d0eb97d..67e1c4a 100644 (file)
@@ -45,6 +45,11 @@ namespace Adaptor
  */
 #define DALI_ENV_PERFORMANCE_TIMESTAMP_OUTPUT "DALI_PERFORMANCE_TIMESTAMP_OUTPUT"
 
+/**
+ * Allow control and monitoring of DALi via the network
+ */
+#define DALI_ENV_NETWORK_CONTROL "DALI_NETWORK_CONTROL"
+
 // environment variable for enabling/disabling fps tracking
 #define DALI_ENV_FPS_TRACKING "DALI_FPS_TRACKING"
 
index 4336b56..94c99d5 100644 (file)
@@ -9,6 +9,10 @@ base_adaptor_src_files = \
   $(base_adaptor_src_dir)/vsync-notifier.cpp \
   $(base_adaptor_src_dir)/performance-logging/frame-time-stamp.cpp \
   $(base_adaptor_src_dir)/environment-options.cpp \
+  $(base_adaptor_src_dir)/performance-logging/networking/network-performance-protocol.cpp \
+  $(base_adaptor_src_dir)/performance-logging/networking/network-performance-client.cpp \
+  $(base_adaptor_src_dir)/performance-logging/networking/network-performance-server.cpp \
+  $(base_adaptor_src_dir)/performance-logging/networking/event/automation.cpp \
   $(base_adaptor_src_dir)/performance-logging/frame-time-stats.cpp \
   $(base_adaptor_src_dir)/performance-logging/performance-marker.cpp \
   $(base_adaptor_src_dir)/performance-logging/statistics/stat-context.cpp \
index e6714c9..d202da5 100644 (file)
@@ -24,7 +24,8 @@
 
 // INTERNAL INCLUDES
 #include <base/interfaces/egl-factory-interface.h>
-#include <base/interfaces/trigger-event-interface.h>
+#include <base/interfaces/trigger-event-factory-interface.h>
+#include <base/interfaces/socket-factory-interface.h>
 #include <base/interfaces/performance-interface.h>
 #include <base/interfaces/vsync-monitor-interface.h>
 #include <base/interfaces/kernel-trace-interface.h>
@@ -77,6 +78,16 @@ public:
   virtual TriggerEventInterface& GetTriggerEventInterface()  = 0;
 
   /**
+   * @return trigger event factory interface
+   */
+  virtual TriggerEventFactoryInterface& GetTriggerEventFactoryInterface() = 0;
+
+  /**
+   * @return socket factory interface
+   */
+  virtual SocketFactoryInterface& GetSocketFactoryInterface() = 0;
+
+  /**
    * @return render surface
    */
   virtual RenderSurface* GetRenderSurfaceInterface()  = 0;
index 3f41f97..a90584f 100644 (file)
@@ -72,10 +72,10 @@ public:
   enum TimeStampOutput
   {
     NO_TIME_STAMP_OUTPUT         = 0,
-    OUTPUT_DALI_LOG              = 1 << 0, ///< Bit 1 (1), log markers to DALi log
-    OUTPUT_KERNEL_TRACE          = 1 << 1, ///< Bit 2 (2), log makers to kernel trace
-    OUTPUT_SYSTEM_TRACE          = 1 << 2, ///< Bit 3 (4), log markers to system trace
-    OUTPUT_NETWORK               = 1 << 3, ///< Bit 4 (8), log markers to network client
+    OUTPUT_DALI_LOG              = 1 << 0, ///< Bit 0 (1), log markers to DALi log
+    OUTPUT_KERNEL_TRACE          = 1 << 1, ///< Bit 1 (2), log makers to kernel trace
+    OUTPUT_SYSTEM_TRACE          = 1 << 2, ///< Bit 2 (4), log markers to system trace
+    OUTPUT_NETWORK               = 1 << 3, ///< Bit 3 (8), log markers to network client
   };
 
   /**
diff --git a/adaptors/base/interfaces/socket-factory-interface.h b/adaptors/base/interfaces/socket-factory-interface.h
new file mode 100644 (file)
index 0000000..fea89cb
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_BASE_SOCKET_FACTORY_INTERFACE_H__
+#define __DALI_INTERNAL_ADAPTOR_BASE_SOCKET_FACTORY_INTERFACE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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 <base/interfaces/socket-interface.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+
+/**
+ * @brief abstract class to create and destroy sockets
+ */
+class SocketFactoryInterface
+{
+public:
+
+  /**
+   * @brief Create a new socket
+   * @param protocol network protocol
+   * @return true on success, false on failure
+   */
+   virtual SocketInterface* NewSocket( SocketInterface::Protocol protocol  ) = 0;
+
+   /**
+    * @brief destroy a socket
+    * @param[in] socket socket to destroy
+    */
+   virtual void DestroySocket( SocketInterface* socket  ) = 0;
+
+protected:
+
+  /**
+   * @brief Constructor
+   */
+   SocketFactoryInterface( )
+  {
+  }
+
+  /**
+   * @brief Virtual destructor
+   */
+  virtual ~SocketFactoryInterface()
+  {
+  }
+
+private:
+
+  // Undefined copy constructor.
+  SocketFactoryInterface( const SocketFactoryInterface& );
+
+  // Undefined assignment operator.
+  SocketFactoryInterface& operator=( const SocketFactoryInterface& );
+
+};
+
+
+
+} // Adaptor
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_BASE_SOCKET_FACTORY_INTERFACE_H__
diff --git a/adaptors/base/interfaces/socket-interface.h b/adaptors/base/interfaces/socket-interface.h
new file mode 100644 (file)
index 0000000..e76af50
--- /dev/null
@@ -0,0 +1,198 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_BASE_SOCKET_INTERFACE_H__
+#define __DALI_INTERNAL_ADAPTOR_BASE_SOCKET_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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 <stdint.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+
+/**
+ * @brief Abstract socket interface.
+ * The typical usage is:
+ *
+ * @code
+ *
+ * SocketFactory::NewSocket( SocketInterface::TCP );
+ * socket->ReuseAddress( true );
+ * socket->Bind( port );
+ * socket->Listen();
+ *
+ * ret = socket->Select();     // call socket->ExitSelect to break from select from another thread
+ * if ( ret == DATA_AVAILABLE )
+ * {
+ *   socket->Read( ...);
+ * }
+ * socket->Close();
+ *
+ * @endcode
+ *
+ */
+class SocketInterface
+{
+public:
+
+  /**
+   * @brief Protocol type
+   */
+  enum Protocol
+  {
+    TCP,          ///< Reliable, connection oriented
+    UDP,          ///< Connection less, no guarantees of packet delivery, ordering
+  };
+
+  /**
+   * @brief check is a socket is open
+   * @return true if the socket is currently open
+   */
+  virtual bool SocketIsOpen() const = 0;
+
+  /**
+   * @brief CloseSocket
+   * @return true on success, false on failure
+   */
+  virtual bool CloseSocket() = 0;
+
+  /**
+   * @brief Socket bind,  associate a local address with a socket ( normally uses AF_INET + INADDR_ANY)
+   * @param[in] port network port
+   * @return true on success, false on failure
+   */
+  virtual bool Bind( uint16_t port ) = 0;
+
+  /**
+   * @brief Indicate a willingness to accept incoming connection requests
+   * @param[in] backlog maximum length of the queue of pending connections.
+   * @return true on success, false on failure
+   */
+  virtual bool Listen( int blacklog) = 0;
+
+  /**
+   * @brief Wait for connection request and make connection
+   * @return new client socket
+   */
+  virtual SocketInterface* Accept() const = 0;
+
+  /**
+   * @brief Select return values
+   */
+  enum SelectReturn
+  {
+    DATA_AVAILABLE,   ///< Data is available to read
+    QUIT,             ///< ExitSelect() has been called on the socket
+    ERROR             ///< Socket error
+  };
+
+  /**
+   * @brief Waits for an event to occur (data available / error)
+   * Returns when
+   * - data has been sent to the socket
+   * - client has closed the connection ( Read will return 0 bytes)
+   * - ExitSelect has been called (returns QUIT)
+   * - There is an error (returns ERROR)
+   * @return DATA_AVAILABLE if data is available
+   */
+  virtual SelectReturn Select() = 0;
+
+  /**
+   * @brief To be called from a separate thread to break out of select
+   */
+  virtual void ExitSelect() = 0;
+
+  /**
+   * @brief Read data from the socket
+   * @param[out] buffer data
+   * @param[in] bufferSizeInBytes buffer size in bytes
+   * @param[out] bytesRead number of bytes read
+   * @return true on success, false on failure
+   */
+  virtual bool Read( void* buffer, unsigned int bufferSizeInBytes, unsigned int& bytesRead  ) = 0;
+
+  /**
+   * @brief Send data to the socket
+   * @param[in] buffer data to write
+   * @param[in] bufferSizeInBytes buffer size in write
+   * @return true on success, false on failure
+   */
+  virtual bool Write( const void* buffer, unsigned int bufferSizeInBytes ) = 0;
+
+  //
+  // Common socket options. Please add more as required.
+  // These should be wrappers around the setsockopt API
+
+  /**
+   * @brief Whether the SO_REUSEADDR is enabled or not.
+   * @param[in] reuse flag.
+   * @return true on success, false on failure
+   */
+  virtual bool ReuseAddress( bool reUse ) = 0;
+
+  /**
+   * @brief Socket buffer type
+   */
+  enum BufferType
+  {
+    SEND_BUFFER,        ///< (SO_SNDBUF) Send buffer size
+    RECIEVE_BUFFER      ///< (SO_RCVBUF) Size of buffer allocated to hold data arriving to the socket
+  };
+
+  /**
+   * @brief Set the send and recieve buffer sizes ( SO_SNDBUF, SO_RCVBUF )
+   * @param[in] type buffer type
+   * @param[in] size buffer size
+   * @return true on success, false on failure
+   */
+  virtual bool SetBufferSize( BufferType type, unsigned int size ) = 0;
+
+protected:
+
+  /**
+   * @brief Constructor
+   */
+  SocketInterface( )
+  {
+  }
+
+  /**
+   * @brief virtual destructor
+   */
+  virtual ~SocketInterface()
+  {
+  }
+
+private:
+
+  // Undefined copy constructor.
+  SocketInterface( const SocketInterface& );
+
+  // Undefined assignment operator.
+  SocketInterface& operator=( const SocketInterface& );
+
+};
+
+
+} // Adaptor
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_BASE_SOCKET_INTERFACE_H__
diff --git a/adaptors/base/performance-logging/networking/client-send-data-interface.h b/adaptors/base/performance-logging/networking/client-send-data-interface.h
new file mode 100644 (file)
index 0000000..905fc41
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_CLIENT_SEND_DATA_INTERFACE_H__
+#define __DALI_INTERNAL_ADAPTOR_CLIENT_SEND_DATA_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * @brief  Abstract interface used to transmit data to a client
+ */
+class ClientSendDataInterface
+{
+public:
+
+  /**
+   * @brief Sends data to the client
+   * @param[in] data pointer to some data
+   * @param[in] bufferSizeInBytes how big the buffer is in bytes
+   * @param[in] clientId unique client id to send the data to
+   */
+  virtual void SendData( const char* const data, unsigned int bufferSizeInBytes, unsigned int clientId ) = 0;
+
+
+protected:
+
+  /**
+   * @brief  Constructor
+   */
+  ClientSendDataInterface()
+  {
+  }
+
+  /**
+   * @brief Virtual Destructor
+   */
+  virtual ~ClientSendDataInterface()
+  {
+  }
+
+private:
+
+  // Undefined copy constructor.
+  ClientSendDataInterface( const ClientSendDataInterface& );
+
+  // Undefined assignment operator.
+  ClientSendDataInterface& operator=( const ClientSendDataInterface& );
+
+};
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_CLIENT_SEND_DATA_INTERFACE_H__
diff --git a/adaptors/base/performance-logging/networking/event/automation.cpp b/adaptors/base/performance-logging/networking/event/automation.cpp
new file mode 100644 (file)
index 0000000..c8a0705
--- /dev/null
@@ -0,0 +1,340 @@
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// CLASS HEADER
+#include "automation.h"
+
+// EXTERNAL INCLUDES
+#include <sstream>
+#include <iomanip>
+#include <stdio.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/debug.h>
+
+
+namespace  // un-named namespace
+{
+
+const unsigned int MAX_SET_PROPERTY_STRING_LENGTH = 256; ///< maximum length of a set property command
+
+class JsonPropertyValue
+{
+public:
+  JsonPropertyValue( const std::string& str )
+  {
+    std::size_t strLength = str.length();
+
+    mString.reserve( strLength );
+    for( std::size_t i = 0; i < strLength; ++i )
+    {
+      const char c = str[i];
+      if( (c != '[') && c != ']')
+      {
+        mString.push_back( c );
+      }
+    }
+
+  }
+  std::string GetString() const
+  {
+    return mString;
+  }
+  float GetFloat() const
+  {
+    return atof( mString.c_str() );
+  }
+  int GetInt()
+  {
+    return atoi( mString.c_str() );
+  }
+  bool GetBoolean()
+  {
+    return (GetInt() != 0);
+  }
+
+  Dali::Vector2 GetVector2()
+  {
+    Dali::Vector2 vec2;
+
+    int count = sscanf( mString.c_str(),"%f,%f",&vec2.x,&vec2.y );
+    if( count != 2 )
+    {
+      DALI_LOG_ERROR("Bad format");
+    }
+    return vec2;
+  }
+
+  Dali::Vector3 GetVector3()
+  {
+    Dali::Vector3 vec3;
+
+    int count = sscanf( mString.c_str(),"%f,%f,%f",&vec3.x,&vec3.y,&vec3.z );
+    if( count != 3 )
+    {
+      DALI_LOG_ERROR("Bad format");
+    }
+    return vec3;
+  }
+
+  Dali::Vector4 GetVector4()
+  {
+    Dali::Vector4 vec4;
+
+    int count = sscanf( mString.c_str(),"%f,%f,%f,%f", &vec4.x, &vec4.y, &vec4.z, &vec4.w );
+    if( count != 4 )
+    {
+      DALI_LOG_ERROR("Bad format");
+    }
+    return vec4;
+  }
+
+private:
+  std::string mString;
+
+};
+
+void SetProperty( Dali::Handle handle, int propertyId, JsonPropertyValue& propertyValue )
+{
+  Dali::Property::Type type = handle.GetPropertyType( propertyId );
+  switch( type )
+  {
+  case Dali::Property::FLOAT:
+  {
+    float val = propertyValue.GetFloat();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::INTEGER:
+  {
+    int val = propertyValue.GetInt();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::BOOLEAN:
+  {
+    bool val = propertyValue.GetBoolean();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::STRING:
+  {
+    std::string str = propertyValue.GetString();
+    handle.SetProperty( propertyId, Dali::Property::Value( str ) );
+    break;
+  }
+  case Dali::Property::VECTOR2:
+  {
+    Dali::Vector2 val = propertyValue.GetVector2();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::VECTOR3:
+  {
+    Dali::Vector3 val = propertyValue.GetVector3();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::VECTOR4:
+  {
+    Dali::Vector4 val = propertyValue.GetVector4();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  default:
+  {
+    break;
+  }
+  }
+}
+
+int SetProperties( const std::string& setPropertyMessage )
+{
+  std::istringstream iss( setPropertyMessage );
+  std::string token;
+  getline( iss, token, '|' ); // swallow command name
+  while( getline( iss, token, '|' ) )
+  {
+    std::string actorId, propName, propValue;
+    if( token.compare( "---" ) != 0 )
+    {
+      std::istringstream propss( token );
+      getline( propss, actorId, ';' );
+      getline( propss, propName, ';' );
+      getline( propss, propValue );
+
+      Dali::Actor root = Dali::Stage::GetCurrent().GetRootLayer();
+      int id = atoi( actorId.c_str() );
+      Dali::Actor a = root.FindChildById( id );
+      if( a )
+      {
+        // lookup by name for custom properties
+        int propId = a.GetPropertyIndex( propName );
+        if( propId > 0 )
+        {
+          JsonPropertyValue pv( propValue );
+          SetProperty( a, propId, pv );
+        }
+
+      }
+    }
+  }
+
+  return 0;
+}
+
+
+}; //   un-named namespace
+
+inline std::string Quote( const std::string& in )
+{
+  return (std::string( "\"" ) + in + std::string( "\"" ));
+}
+
+template<class T>
+std::string ToString( T i )
+{
+  std::stringstream ss;
+  std::string s;
+  ss << i;
+  s = ss.str();
+
+  return s;
+}
+
+
+// currently rotations are output in Euler format ( may change)
+void AppendPropertyNameAndValue( Dali::Handle handle, int propertyIndex, std::ostringstream& outputStream)
+{
+  // get the property name and the value as a string
+  std::string propertyName( handle.GetPropertyName( propertyIndex ) );
+  Dali::Property::Value value = handle.GetProperty( propertyIndex );
+
+  // Apply quotes around the property name and the value.. "color", "1.3, 3.4, 2.6"
+  outputStream << "\"" << propertyName << "\"" << ",";
+  outputStream << "\"" << value << "\"";
+
+}
+
+bool ExcludeProperty( int propIndex )
+{
+  return (propIndex == Dali::Actor::Property::NAME    ||
+
+      // all of these are repeat properties of values in vectors....
+      // We don't really need these in the UI
+      propIndex == Dali::Actor::Property::ANCHOR_POINT_X || propIndex == Dali::Actor::Property::ANCHOR_POINT_Y || propIndex == Dali::Actor::Property::ANCHOR_POINT_Z || propIndex == Dali::Actor::Property::PARENT_ORIGIN_X
+      || propIndex == Dali::Actor::Property::PARENT_ORIGIN_Y || propIndex == Dali::Actor::Property::PARENT_ORIGIN_Z || propIndex == Dali::Actor::Property::COLOR_RED || propIndex == Dali::Actor::Property::COLOR_GREEN
+      || propIndex == Dali::Actor::Property::COLOR_BLUE || propIndex == Dali::Actor::Property::COLOR_ALPHA|| propIndex == Dali::Actor::Property::POSITION_X || propIndex == Dali::Actor::Property::POSITION_Y
+      || propIndex == Dali::Actor::Property::POSITION_Z|| propIndex == Dali::Actor::Property::SIZE_WIDTH|| propIndex == Dali::Actor::Property::SIZE_HEIGHT || propIndex == Dali::Actor::Property::SCALE_X || propIndex == Dali::Actor::Property::SCALE_Y
+      || propIndex == Dali::Actor::Property::SCALE_Z || propIndex == Dali::Actor::Property::SIZE_DEPTH);
+}
+
+std::string DumpJson( Dali::Actor actor, int level )
+{
+  // All the information about this actor
+  std::ostringstream msg;
+  msg << "{ " << Quote( "Name" ) << " : " << Quote( actor.GetName() ) << ", " << Quote( "level" ) << " : " << level << ", " << Quote( "id" ) << " : " << actor.GetId() << ", " << Quote( "IsVisible" )
+      << " : " << actor.IsVisible() << ", " << Quote( "IsSensitive" ) << " : " << actor.IsSensitive();
+
+  msg << ", " << Quote( "properties" ) << ": [ ";
+
+  Dali::Property::IndexContainer indices;
+  actor.GetPropertyIndices( indices );
+
+  Dali::Property::IndexContainer::iterator iter = indices.begin();
+  int numCustom = 0;
+  for( ; iter != indices.end() ; iter++ )
+  {
+    int i = *iter;
+    if( !ExcludeProperty( i ) )
+    {
+      if( numCustom++ != 0 )
+      {
+        msg << ", ";
+      }
+      msg << "[";
+
+      AppendPropertyNameAndValue( actor, i,msg );
+
+      msg << "]";
+    }
+  }
+  msg << "]";
+  msg << ", " << Quote( "children" ) << " : [ ";
+
+  // Recursively dump all the children as well
+  for( unsigned int i = 0 ; i < actor.GetChildCount() ; ++i )
+  {
+    if( i )
+    {
+      msg << " , ";
+    }
+    msg << DumpJson( actor.GetChildAt( i ), level + 1 );
+  }
+  msg << "] }";
+
+  return msg.str();
+}
+
+std::string GetActorTree()
+{
+  Dali::Actor actor = Dali::Stage::GetCurrent().GetRootLayer();
+  std::string str = DumpJson( actor, 0 );
+  return str;
+}
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace Automation
+{
+
+void SetProperty( const std::string& message )
+{
+  // check the set property length is within range
+  if( message.length() > MAX_SET_PROPERTY_STRING_LENGTH )
+  {
+    DALI_LOG_ERROR("SetProperty message length too long, size = %ul\n", message.length());
+    return;
+  }
+
+  SetProperties( message );
+}
+
+void DumpScene( unsigned int clientId, ClientSendDataInterface* sendData )
+{
+  char buf[32];
+  std::string json = GetActorTree();
+  int length = json.length();
+  sprintf( buf, "%d\n", length );
+  std::string header( buf );
+  json = buf + json;
+  sendData->SendData( json.c_str(), json.length(), clientId );
+}
+
+} // namespace Automation
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
diff --git a/adaptors/base/performance-logging/networking/event/automation.h b/adaptors/base/performance-logging/networking/event/automation.h
new file mode 100644 (file)
index 0000000..4194f09
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_AUTOMATION_H__
+#define __DALI_INTERNAL_ADAPTOR_AUTOMATION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <base/performance-logging/networking/client-send-data-interface.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * @brief The automation functions allow a way to control Dali via a network socket.
+ *
+ * The functions must be called from the event thread only.
+ *
+ * Any functions which require a response to be sent back to the network client
+ * use the ClientSendDataInterface interface.
+
+ * E.g.
+ * Dali network client thread            <---- "dump_scene" from network
+ * Dali main thread       "json data"    ----->   network
+ *
+ */
+namespace Automation
+{
+
+/**
+ * @brief Sets properties on an Actor.
+ * No ClientSendDataInterface required, as no response is sent back
+ * @param[in] message set property message
+ */
+void SetProperty( const std::string& message );
+
+
+/**
+ * @brief Dumps the actor tree to the client
+ * @param[in] clientId unique network client id
+ * @param[in] sendData interface to transmit data to the client
+ */
+void DumpScene( unsigned int clientId, ClientSendDataInterface* sendData );
+
+
+} // namespace Automation
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+#endif
diff --git a/adaptors/base/performance-logging/networking/network-performance-client.cpp b/adaptors/base/performance-logging/networking/network-performance-client.cpp
new file mode 100644 (file)
index 0000000..f11d825
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// CLASS HEADER
+#include "network-performance-client.h"
+
+// EXTERNAL INCLUDES
+#include <stdio.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <base/interfaces/socket-interface.h>
+#include <base/performance-logging/networking/network-performance-protocol.h>
+#include <base/performance-logging/networking/event/automation.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+const char UNKNOWN_CMD[]= "Command or parameter invalid, type help for list of commands\n";
+
+
+/**
+ * helper class to store data along with the automation callback.
+ */
+class AutomationCallback: public CallbackBase
+{
+public:
+
+  /**
+   * instead of using templates, or having different callback classes for each callback
+   * we use a command id that decides which static function to call on the Automation class.
+   */
+  enum CommandId
+  {
+    UNKNOWN_COMMAND,
+    SET_PROPERTY,
+    DUMP_SCENE
+  };
+
+  AutomationCallback(  unsigned int clientId, ClientSendDataInterface& sendDataInterface )
+  :CallbackBase( reinterpret_cast< void* >( this ),
+                 NULL, // we get the dispatcher to call function directly
+                 reinterpret_cast< CallbackBase::Dispatcher>( &AutomationCallback::Dispatcher) ),
+  mSendDataInterface( sendDataInterface ),
+  mCommandId( UNKNOWN_COMMAND ),
+  mClientId( clientId )
+  {}
+
+  void AssignSetPropertyCommand( std::string setPropertyCommand )
+  {
+    mCommandId = SET_PROPERTY;
+    mPropertyCommand = setPropertyCommand;
+  }
+  void AssignDumpSceneCommand()
+  {
+     mCommandId = DUMP_SCENE;
+  }
+
+  void RunCallback()
+  {
+    switch( mCommandId )
+    {
+      case SET_PROPERTY:
+      {
+        Automation::SetProperty( mPropertyCommand );
+        break;
+      }
+      case DUMP_SCENE:
+      {
+        Automation::DumpScene( mClientId, &mSendDataInterface);
+        break;
+      }
+      default:
+      {
+        DALI_ASSERT_DEBUG( 0 && "Unknown command");
+        break;
+      }
+    }
+  }
+  static void Dispatcher( CallbackBase& base )
+  {
+    AutomationCallback& automationCallback( static_cast< AutomationCallback& >( base) );
+    automationCallback.RunCallback();
+  }
+
+private:
+
+  std::string mPropertyCommand;                   ///< property command
+  ClientSendDataInterface& mSendDataInterface;    ///< Abstract client send data interface
+  CommandId mCommandId;                           ///< command id
+  const unsigned int mClientId;                   ///< client id
+};
+
+} // unnamed namespace
+
+NetworkPerformanceClient::NetworkPerformanceClient(  SocketInterface *socket,
+                                                     unsigned int clientId,
+                                                     TriggerEventFactoryInterface& triggerEventFactory,
+                                                     ClientSendDataInterface& sendDataInterface,
+                                                     SocketFactoryInterface& socketFactory )
+: mSocket( socket ),
+  mMarkerBitmask( PerformanceMarker::FILTERING_DISABLED ),
+  mTriggerEventFactory( triggerEventFactory ),
+  mSendDataInterface( sendDataInterface ),
+  mSocketFactoryInterface( socketFactory ),
+  mClientId( clientId ),
+  mConsoleClient(false)
+{
+
+}
+
+NetworkPerformanceClient::~NetworkPerformanceClient()
+{
+  if( mSocket->SocketIsOpen() )
+  {
+    mSocket->CloseSocket();
+  }
+  mSocketFactoryInterface.DestroySocket( mSocket );
+}
+
+unsigned int NetworkPerformanceClient::GetId() const
+{
+  return mClientId;
+}
+
+SocketInterface& NetworkPerformanceClient::GetSocket()
+{
+  return *mSocket;
+}
+
+bool NetworkPerformanceClient::WriteSocket( const void* buffer, unsigned int bufferSizeInBytes )
+{
+  return mSocket->Write( buffer, bufferSizeInBytes );
+}
+
+bool NetworkPerformanceClient::TransmitMarker( const PerformanceMarker& marker, const char* const description )
+{
+  if( ! marker.IsFilterEnabled( mMarkerBitmask ) )
+  {
+    return true;
+  }
+  if( mConsoleClient )
+  {
+    // write out the time stamp
+    char buffer[64];
+    int size = snprintf( buffer, sizeof(buffer),"%d.%06d (seconds), %s\n",
+                                    marker.GetTimeStamp().seconds,
+                                    marker.GetTimeStamp().microseconds,
+                                    description );
+
+   return mSocket->Write( buffer, size );
+
+  }
+
+  // todo serialize the data
+  return false;
+}
+
+void NetworkPerformanceClient::ExitSelect()
+{
+  mSocket->ExitSelect();
+}
+
+
+void NetworkPerformanceClient::ProcessCommand( char* buffer, unsigned int bufferSizeInBytes )
+{
+  // if connected via console, then strip off the carriage return, and switch to console mode
+  if( buffer[ bufferSizeInBytes - 1] == '\n')
+  {
+    buffer[ bufferSizeInBytes - 1] = 0;
+    mConsoleClient = true;
+  }
+  unsigned int param(0);
+  std::string stringParam;
+  PerformanceProtocol::CommandId commandId( PerformanceProtocol::UNKNOWN_COMMAND );
+
+  bool ok =  PerformanceProtocol::GetCommandId( buffer, bufferSizeInBytes, commandId, param, stringParam );
+  if( !ok )
+  {
+    WriteSocket( UNKNOWN_CMD, sizeof(UNKNOWN_CMD) );
+    return;
+  }
+  std::string response;
+
+  switch( commandId )
+  {
+    case PerformanceProtocol::HELP_MESSAGE:
+    {
+      response = PerformanceProtocol::GetHelpMessage();
+      break;
+    }
+
+    case PerformanceProtocol::ENABLE_TIME_MARKER_BIT_MASK:
+    {
+      mMarkerBitmask  = static_cast<  PerformanceMarker::MarkerFilter >( param );
+      response = "enable time marker ";
+      break;
+    }
+
+    case PerformanceProtocol::DUMP_SCENE_GRAPH:
+    {
+      // this needs to be run on the main thread, use the trigger event....
+      AutomationCallback* callback = new AutomationCallback( mClientId, mSendDataInterface );
+      callback->AssignDumpSceneCommand();
+
+      // create a trigger event that automatically deletes itself after the callback has run in the main thread
+      TriggerEventInterface *interface = mTriggerEventFactory.CreateTriggerEvent( callback, TriggerEventInterface::DELETE_AFTER_TRIGGER );
+
+      // asynchronous call, the call back will be run sometime later on the main thread
+      interface->Trigger();
+      break;
+    }
+
+    case PerformanceProtocol::SET_PROPERTIES:
+    {
+      // this needs to be run on the main thread, use the trigger event....
+      AutomationCallback* callback = new AutomationCallback( mClientId, mSendDataInterface );
+      callback->AssignSetPropertyCommand( stringParam );
+
+      // create a trigger event that automatically deletes itself after the callback has run in the main thread
+      TriggerEventInterface *interface = mTriggerEventFactory.CreateTriggerEvent( callback, TriggerEventInterface::DELETE_AFTER_TRIGGER );
+
+      // asynchronous call, the call back will be run sometime later on the main thread
+      interface->Trigger();
+      break;
+    }
+
+    case PerformanceProtocol::LIST_METRICS_AVAILABLE:
+    case PerformanceProtocol::ENABLE_METRIC:
+    case PerformanceProtocol::DISABLE_METRIC:
+    {
+      response="Metrics currently not supported";
+      break;
+    }
+    default:
+    {
+      response = UNKNOWN_CMD;
+      break;
+    }
+  }
+  if( ! response.empty() )
+  {
+    // add a carriage return for console clients
+    if( mConsoleClient )
+    {
+      response+="\n";
+    }
+    WriteSocket( response.c_str(), response.length()  );
+  }
+}
+
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
diff --git a/adaptors/base/performance-logging/networking/network-performance-client.h b/adaptors/base/performance-logging/networking/network-performance-client.h
new file mode 100644 (file)
index 0000000..8784925
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_CLIENT_H__
+#define __DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_CLIENT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <base/performance-logging/performance-marker.h>
+#include <base/interfaces/trigger-event-factory-interface.h>
+#include <base/performance-logging/networking/client-send-data-interface.h>
+#include <base/interfaces/socket-factory-interface.h>
+
+namespace boost
+{
+class thread;
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ *  @brief Network Performance client
+ *
+ *  Every time a client connects to Dali, a NetworkPerformanceClient object is created.
+ *  It is responsible for processing incoming commands, and storing the client state
+ *  (e.g. what performance markers it wants).
+ *
+ *  Certain commands such as dump-scene need to be run on the main Dali event thread.
+ *  To achieve this, a trigger event is used which executes a function on the main thread.
+ *  The sendDataInterface is then used with the client id to transmit the data to the client.
+ *  The reason for using a client id is because the client
+ *  can be deleted in between receiving a command and sending a response.
+ *  E.g.
+ *  NetworkPerformanceClient (own thread, id 5)  <---  Dump Scene Command
+ *  delete NetworkPerformanceClient              <---  Connection closed
+ *  MainThread. Send scene data to client 5. Client 5 has been deleted so don't send the data.
+ *
+ */
+class NetworkPerformanceClient
+{
+public:
+
+  /**
+   * @brief Constructor
+   * @param socket socket interface
+   * @param clientId unique client id
+   * @param triggerEventFactory used to create trigger events
+   * @param sendDataInterface used to send data to the socket from main thread
+   * @param SocketFactoryInterface used to delete the socket when the client is destroyed
+   */
+  NetworkPerformanceClient( SocketInterface *socket,
+                            unsigned int clientId,
+                            TriggerEventFactoryInterface& triggerEventFactory,
+                            ClientSendDataInterface& sendDataInterface,
+                            SocketFactoryInterface& socketFactory );
+
+  /**
+   * @brief Destructor
+   */
+  ~NetworkPerformanceClient();
+
+  /**
+   * @return client unique id
+   */
+  unsigned int GetId() const;
+
+  /**
+   * @return socket interface
+   */
+  SocketInterface& GetSocket();
+
+  /**
+   * @brief Write data to a socket. Can be called from any thread
+   * @copydoc Dali::SocketInterface::Send
+   */
+  bool WriteSocket( const void* buffer, unsigned int bufferSizeInBytes );
+
+  /**
+   * @brief Process a command
+   * @param buffer pointer to command data
+   * @param bufferSizeInBytes how big the buffer is in bytes
+   */
+  void ProcessCommand( char* buffer, unsigned int bufferSizeInBytes );
+
+  /**
+   * @brief Write a marker to the socket, if this client is filtering this marker.
+   * @param marker
+   */
+  bool TransmitMarker( const PerformanceMarker& marker, const char* const description );
+
+  /**
+   * @brief If the client is waiting inside a select statement, this will cause it
+   * to break out.
+   */
+  void ExitSelect();
+
+private:
+
+  SocketInterface* mSocket;                             ///< socket interface
+  PerformanceMarker::MarkerFilter mMarkerBitmask;       ///< What markers are currently filtered
+  TriggerEventFactoryInterface& mTriggerEventFactory;   ///< Trigger event factory
+  ClientSendDataInterface& mSendDataInterface;          ///< used to send data to a client from the main event thread
+  SocketFactoryInterface& mSocketFactoryInterface;      ///< used to delete the socket
+  unsigned int mClientId;                               ///< unique client id
+  bool mConsoleClient;                                  ///< if connected via a console then all responses are in ASCII, not binary packed data.
+
+};
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+#endif
diff --git a/adaptors/base/performance-logging/networking/network-performance-protocol.cpp b/adaptors/base/performance-logging/networking/network-performance-protocol.cpp
new file mode 100644 (file)
index 0000000..91ccb7b
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+// CLASS HEADER
+#include "network-performance-protocol.h"
+
+// EXTERNAL INCLUDES
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace Dali
+{
+
+namespace PerformanceProtocol
+{
+
+namespace
+{
+
+/**
+ * Command parameter type
+ */
+enum PARAMETER_TYPE
+{
+  NO_PARAMS,
+  UNSIGNED_INT,
+  STRING
+};
+
+/**
+ * Command information structure
+ */
+struct CommandInfo
+{
+  CommandId     cmdId;
+  CommandString cmdString;
+  PARAMETER_TYPE paramType;
+};
+
+/**
+ * Command lookup table
+ */
+CommandInfo CommandLookup[]=
+{
+  {  HELP_MESSAGE               , "help"               ,NO_PARAMS     },
+  {  ENABLE_METRIC              , "enable_metric"      ,UNSIGNED_INT  },
+  {  DISABLE_METRIC             , "disable_metric"     ,UNSIGNED_INT  },
+  {  LIST_METRICS_AVAILABLE     , "list_metrics"       ,NO_PARAMS     },
+  {  ENABLE_TIME_MARKER_BIT_MASK, "set_marker",         UNSIGNED_INT  },
+  {  DUMP_SCENE_GRAPH           , "dump_scene"         ,NO_PARAMS     },
+  {  SET_PROPERTIES             , "set_properties"     ,STRING        },
+  {  UNKNOWN_COMMAND            , "unknown"            ,NO_PARAMS     }
+};
+const unsigned int CommandLookupLength = sizeof( CommandLookup ) /sizeof( CommandInfo );
+
+#define GREEN  "\033[01;32m"
+#define NORMAL  "\e[m"
+#define PARAM "\033[22;32m"
+#define YELLOW "\033[01;33m"
+
+const char* const helpMsg =
+    YELLOW
+    "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
+    "  Dali performance console                           \n"
+    "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" NORMAL
+    GREEN " list_metrics " NORMAL " - list available metrics\n"
+    GREEN " enable_metric " PARAM " metricId" NORMAL " - enable a metric \n"
+    GREEN " disable_metric "PARAM " metricId" NORMAL " - disable a metric\n\n"
+    GREEN " set_marker " PARAM " value " NORMAL "-output Dali markers\n"
+    "            : Bit 0  = V_SYNC (1)\n"
+    "            : Bit 1  = Update task (2)\n"
+    "            : Bit 2  = Render task (4) \n"
+    "            : Bit 3  = Event Processing task (8)\n"
+    "            : Bit 4  = SwapBuffers (16)\n"
+    "            : Bit 5  = Life cycle events  (32)\n"
+    "            : Bit 6  = Resource event (64)\n"
+    "\n"
+    GREEN" set_properties "NORMAL " - set an actor property command. Format:\n\n"
+    GREEN" set_properties "PARAM"|ActorIndex;Property;Value|" NORMAL ", e.g: \n"
+    GREEN" set_properties " PARAM "|178;Size;[ 144.0, 144.0, 144.0 ]|178;Color;[ 1.0, 1,0, 1.0 ]|\n"
+    "\n"
+    GREEN " dump_scene" NORMAL " - dump the current scene in json format\n";
+
+} // un-named namespace
+
+bool GetCommandId( const char* const commandString, unsigned int lengthInBytes, CommandId& commandId, unsigned int& intParam, std::string& stringParam  )
+{
+  commandId = UNKNOWN_COMMAND;
+  intParam = 0;
+
+  // the command list is small so just do a O(n) search for the commandID.
+  for( unsigned int i = 0 ; i < CommandLookupLength; ++i )
+  {
+    if( strncmp( commandString, CommandLookup[i].cmdString ,strlen(CommandLookup[i].cmdString  )) == 0 )
+    {
+      commandId = CommandLookup[i].cmdId;
+
+      // if the command has a parameter read it
+      if( CommandLookup[i].paramType ==  UNSIGNED_INT)
+      {
+        int count = sscanf(commandString,"%*s %d",&intParam);
+        if( count != 1 )
+        {
+          // missing parameter
+          return false;
+        }
+      }
+      else if (CommandLookup[i].paramType == STRING )
+      {
+        char* charParam( NULL );
+        // allocates the character array
+        int count = sscanf(commandString,"%*s %ms",&charParam);
+        if( count != 1 )
+        {
+          // missing parameter
+          return false;
+        }
+        stringParam = std::string( charParam);
+        free(charParam);
+      }
+      return true;
+    }
+  }
+  // not found
+  return false;
+}
+
+bool GetCommandString( CommandId commandId, CommandString& commandString )
+{
+  for( unsigned int i = 0; i < CommandLookupLength; ++i)
+  {
+    if( CommandLookup[ i ].cmdId == commandId )
+    {
+      strncpy( commandString,  CommandLookup[ i ].cmdString, strlen(CommandLookup[ i ].cmdString) );
+      return true;
+    }
+  }
+  strncpy( commandString, CommandLookup[ UNKNOWN_COMMAND ].cmdString, MAX_COMMAND_STRING_LENGTH);
+  return false;
+}
+
+const char* const GetHelpMessage()
+{
+  return helpMsg;
+}
+
+
+} // namespace PerformanceProtocol
+
+} // namespace Dali
diff --git a/adaptors/base/performance-logging/networking/network-performance-protocol.h b/adaptors/base/performance-logging/networking/network-performance-protocol.h
new file mode 100644 (file)
index 0000000..e3dfcb1
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_PROTOCOL_H__
+#define __DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_PROTOCOL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+namespace Dali
+{
+
+namespace PerformanceProtocol
+{
+
+const unsigned int MAX_COMMAND_STRING_LENGTH = 256;  ///< maximum length of a command including null terminator
+
+/**
+ * @brief List of commands id's
+ */
+enum CommandId
+{
+  HELP_MESSAGE            = 0, ///<  help message
+  ENABLE_METRIC           = 1, ///< enable metric
+  DISABLE_METRIC          = 2, ///< disable metric
+  LIST_METRICS_AVAILABLE  = 3, ///< list  metrics that are available
+  ENABLE_TIME_MARKER_BIT_MASK = 4, ///< bit mask of time markers to enable
+  SET_PROPERTIES            = 5, ///< set property
+  DUMP_SCENE_GRAPH          = 6, ///< dump the scene graph
+  UNKNOWN_COMMAND           = 4096
+};
+
+
+typedef char CommandString[ MAX_COMMAND_STRING_LENGTH ];
+
+/**
+ * @brief given a command id, get the command string
+ * @param[in] commandId command id
+ * @param[out] commandString command string
+ * @return true on success, false on failure
+ */
+bool GetCommandString( CommandId commandId, CommandString& commandString );
+
+/**
+ * @brief given a command string, get the command id and an integer parameter if it exists
+ * @param[in] commandString command string
+ * @param[in] lengthInBytes length of the string
+ * @param[out] commandId command id
+ * @param[out] intParam integer parameter
+ * @param[out] stringParam string parameter
+ * @param true on success, false on failure
+ */
+bool GetCommandId( const char* const commandString,
+                   unsigned int lengthInBytes,
+                   CommandId& commandId,
+                   unsigned int& intParam,
+                   std::string& stringParam);
+
+/**
+ * @return the protocol help message for console users
+ */
+const char* const GetHelpMessage();
+
+} // namespace PerformanceProtocol
+
+} // namespace Dali
+
+#endif //__DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_PROTOCOL_H__
diff --git a/adaptors/base/performance-logging/networking/network-performance-server.cpp b/adaptors/base/performance-logging/networking/network-performance-server.cpp
new file mode 100644 (file)
index 0000000..dbbd3e6
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// CLASS HEADER
+#include "network-performance-server.h"
+
+// EXTERNAL INCLUDES
+#include <boost/thread.hpp>
+
+// INTERNAL INCLUDES
+#include <base/performance-logging/performance-marker.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace // un-named namespace
+{
+const unsigned int SERVER_PORT = 3031;
+const unsigned int MAXIMUM_PORTS_TO_TRY = 10; ///< if port in use, try up to SERVER_PORT + 10
+const unsigned int CONNECTION_BACKLOG = 2;   ///<  maximum length of the queue of pending connections.
+const unsigned int SOCKET_READ_BUFFER_SIZE = 4096;
+typedef Vector< NetworkPerformanceClient*> ClientList;
+}
+
+NetworkPerformanceServer::NetworkPerformanceServer( AdaptorInternalServices& adaptorServices,
+                                                    const EnvironmentOptions& logOptions )
+: mTriggerEventFactory( adaptorServices.GetTriggerEventFactoryInterface() ),
+  mSocketFactory( adaptorServices.GetSocketFactoryInterface() ),
+  mLogOptions( logOptions ),
+  mServerThread( NULL ),
+  mListeningSocket( NULL ),
+  mClientUniqueId( 0 ),
+  mClientCount( 0 ),
+  mLogFunctionInstalled( false )
+{
+}
+
+NetworkPerformanceServer::~NetworkPerformanceServer()
+{
+  Stop();
+
+  if( mLogFunctionInstalled )
+  {
+    mLogOptions.UnInstallLogFunction();
+  }
+}
+
+void NetworkPerformanceServer::Start()
+{
+  // start a thread to listen for incoming connection requests
+  if (! mServerThread )
+  {
+    if( mListeningSocket )
+    {
+      mSocketFactory.DestroySocket( mListeningSocket );
+    }
+    mListeningSocket = mSocketFactory.NewSocket( SocketInterface::TCP);
+    mListeningSocket->ReuseAddress( true );
+
+    bool bound = false;
+    unsigned int basePort = 0;
+
+    // try a small range of ports, so if multiple Dali apps are running you can select
+    // which one to connect to
+    while( !bound && ( basePort <  MAXIMUM_PORTS_TO_TRY ))
+    {
+      bound = mListeningSocket->Bind( SERVER_PORT + basePort );
+      if( !bound )
+      {
+        basePort++;
+      }
+    }
+    if(!bound )
+    {
+      DALI_LOG_ERROR("Failed to bind to a port \n");
+      return;
+    }
+
+    mListeningSocket->Listen( CONNECTION_BACKLOG );
+
+    // start a thread which will block waiting for new connections
+    mServerThread = new boost::thread(boost::bind(&NetworkPerformanceServer::ConnectionListener, this));
+
+    Dali::Integration::Log::LogMessage(Integration::Log::DebugInfo, "~~~ NetworkPerformanceServer started on port %d ~~~ \n",  SERVER_PORT + basePort);
+
+  }
+}
+void NetworkPerformanceServer::Stop()
+{
+  if( !mServerThread )
+  {
+    return;
+  }
+  // close the server thread to prevent any new connections
+  mListeningSocket->ExitSelect();
+
+  // wait for the thread to exit.
+  mServerThread->join();
+
+  // close the socket
+  mListeningSocket->CloseSocket();
+
+  delete mServerThread;
+  mSocketFactory.DestroySocket( mListeningSocket );
+
+  mServerThread = NULL;
+  mListeningSocket = NULL;
+
+  // this will tell all client threads to quit
+  StopClients();
+
+  // wait for all threads to exit and the client count to hit zero
+  {
+    boost::mutex::scoped_lock lock(mClientListMutex);
+
+    while (mClientCount != 0)
+    {
+      mClientCountUpdated.wait(lock);
+    }
+  }
+}
+
+bool NetworkPerformanceServer::IsRunning() const
+{
+  if (mServerThread )
+  {
+    return true;
+  }
+  return false;
+}
+
+void NetworkPerformanceServer::ClientThread( NetworkPerformanceClient* client )
+{
+  mClientCount++;
+
+  SocketInterface& socket( client->GetSocket() );
+
+  for( ;; )
+  {
+    SocketInterface::SelectReturn ret = socket.Select();
+
+    if( ret == SocketInterface::DATA_AVAILABLE )
+    {
+     // Read
+      char buffer[ SOCKET_READ_BUFFER_SIZE ];
+      unsigned int  bytesRead;
+
+      bool ok  = socket.Read( buffer, sizeof( buffer ) , bytesRead);
+      if( ok && ( bytesRead > 0) )
+      {
+        client->ProcessCommand( buffer, bytesRead );
+      }
+      else   // if bytesRead == 0, then client closed connection, if ok == false then an error
+      {
+        DeleteClient( client );
+        return;
+      }
+    }
+    else // ret == QUIT or ERROR
+    {
+      DeleteClient( client);
+      return;
+    }
+  }
+}
+
+void NetworkPerformanceServer::ConnectionListener()
+{
+  // install Dali logging function for this thread
+  if( !mLogFunctionInstalled )
+  {
+    mLogOptions.InstallLogFunction();
+    mLogFunctionInstalled = true;
+  }
+
+  for( ;; )
+  {
+    // this will block, waiting for a client to connect
+    // or for mListeningSocket->ExitSelect() to be called
+
+    SocketInterface::SelectReturn ret = mListeningSocket->Select();
+
+    if( ret == SocketInterface::DATA_AVAILABLE )
+    {
+      SocketInterface* clientSocket = mListeningSocket->Accept();
+
+      // new connection made, spawn a thread to handle it
+      NetworkPerformanceClient* client = AddClient( clientSocket );
+      new boost::thread(boost::bind(&NetworkPerformanceServer::ClientThread, this, client));
+    }
+    else // ret == SocketInterface::QUIT or SocketInterface::ERROR
+    {
+      return;
+    }
+  }
+}
+
+NetworkPerformanceClient* NetworkPerformanceServer::AddClient( SocketInterface* clientSocket )
+{
+  // This function is only called from the listening thread
+  NetworkPerformanceClient* client= new NetworkPerformanceClient(clientSocket,
+                                                                 mClientUniqueId++,
+                                                                 mTriggerEventFactory,
+                                                                 *this,
+                                                                 mSocketFactory);
+
+  // protect the mClients list which can be accessed from multiple threads.
+  boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+
+  mClients.PushBack( client );
+
+  return client;
+}
+
+void NetworkPerformanceServer::DeleteClient( NetworkPerformanceClient* client )
+{
+  // protect the mClients list while modifying
+  boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+
+  // remove from the list, and delete it
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    if( (*iter) == client )
+    {
+      mClients.Erase( iter );
+      delete client;
+
+      // if there server is shutting down, it waits for client count to hit zero
+      mClientCount--;
+
+      // lets the server know the client count has been modified
+      mClientCountUpdated.notify_one();
+      return;
+    }
+  }
+}
+
+void NetworkPerformanceServer::SendData( const char* const data, unsigned int bufferSizeInBytes,unsigned int clientId )
+{
+  if( ! mClientCount )
+  {
+    return;
+  }
+
+  // prevent clients been added / deleted while transmiting data
+  boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    NetworkPerformanceClient* client = (*iter);
+    if( client->GetId() == clientId )
+    {
+      client->WriteSocket(data ,bufferSizeInBytes);
+      return;
+    }
+  }
+}
+
+void NetworkPerformanceServer::TransmitMarker( const PerformanceMarker& marker, const char* const description )
+{
+  if( ! IsRunning() )
+  {
+    return;
+  }
+  // prevent clients been added / deleted while transmiting data
+  boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    NetworkPerformanceClient* client = (*iter);
+    client->TransmitMarker( marker, description );
+  }
+}
+
+
+void NetworkPerformanceServer::StopClients()
+{
+  // prevent clients been added / deleted while stopping all clients
+  boost::mutex::scoped_lock sharedDatalock( mClientListMutex );
+
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    NetworkPerformanceClient* client = (*iter);
+    // stop the client from waiting for new commands, and exit from it's thread
+    client->ExitSelect();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
diff --git a/adaptors/base/performance-logging/networking/network-performance-server.h b/adaptors/base/performance-logging/networking/network-performance-server.h
new file mode 100644 (file)
index 0000000..95bdd8b
--- /dev/null
@@ -0,0 +1,172 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_SERVER_H__
+#define __DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_SERVER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <base/environment-options.h>
+#include <base/performance-logging/networking/network-performance-client.h>
+#include <base/interfaces/adaptor-internal-services.h>
+
+
+namespace boost
+{
+class thread;
+}
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+class SocketInterface;
+class PerformanceMarker;
+
+/**
+ *  @brief  The class listens for incoming connections on a dedicated thread.
+ *
+ *  When a new connection is established a client thread is spawned to
+ *  handle that connection, along with a NetworkPerformanceClient object.
+ *  The NetworkPerformanceClient object performs processing of incoming
+ *  commands and holds the per-client state information for performance monitoring.
+ *
+ *  Server->Start()
+ *  - Open socket
+ *  - Spawns a thread to listen for incoming connections
+ *  <---- New connection
+ *  - Spawns a client thread to communicate with new client
+ *
+ *  Server->Stop()
+ *  - Stops listening thread
+ *  - Stops all client threads
+ */
+class NetworkPerformanceServer : public ClientSendDataInterface
+{
+
+public:
+
+  /**
+   * @brief Constructor
+   * @param[in] adaptorServices adaptor internal services
+   * @param[in] logOptions log options
+   */
+  NetworkPerformanceServer( AdaptorInternalServices& adaptorServices, const EnvironmentOptions& logOptions );
+
+
+  /**
+   * @brief Start the server, to be called form Dali main thread
+   * @pre Can only be called form Dali main thread
+   */
+  void Start();
+
+  /**
+   * @brief Stop the server
+   * @pre Can only be called form Dali main thread
+   */
+  void Stop();
+
+  /**
+   * @return true if the server is running
+   */
+  bool IsRunning() const;
+
+  /**
+   * @brief Transmit a marker to any clients are listening for this marker.
+   * @param[in] marker performance marker
+   * @param[in] description marker description
+   * @pre Can be called from any thread
+   *
+   */
+  void TransmitMarker( const PerformanceMarker& marker, const char* const description );
+
+  /**
+   * Destructor
+   */
+   ~NetworkPerformanceServer();
+
+protected:  // ClientSendDataInterface
+
+  /**
+   * @copydoc ClientSendDataInterface::ClientSendDataInterface()
+   */
+  virtual void SendData( const char* const data, unsigned int bufferSizeInBytes, unsigned int clientId );
+
+private:
+  /**
+   * @brief Client thread function
+   * @param client network client object
+   */
+  void ClientThread( NetworkPerformanceClient* client );
+
+  /**
+   * @brief Stop all client threads
+   */
+  void StopClients();
+
+  /**
+   * @brief Waits for new connections to be made
+   */
+  void ConnectionListener();
+
+  /**
+   * @brief Add a new client to the client list
+   * @param clientSocket client socket
+   * @return client
+   */
+  NetworkPerformanceClient* AddClient( SocketInterface* clientSocket );
+
+  /**
+   * @brief Delete a client from the client list
+   * @param client  network client
+   */
+  void DeleteClient( NetworkPerformanceClient* client );
+
+  NetworkPerformanceServer( const NetworkPerformanceServer& );            ///< undefined copy constructor
+  NetworkPerformanceServer& operator=( const NetworkPerformanceServer& ); ///< undefined assignment operator
+
+
+  TriggerEventFactoryInterface& mTriggerEventFactory;     ///< used to create trigger events
+  SocketFactoryInterface& mSocketFactory;                 ///< used to create sockets
+  const EnvironmentOptions& mLogOptions;                  ///< log options
+  Dali::Vector< NetworkPerformanceClient* > mClients;     ///< list of connected clients
+  boost::thread* mServerThread;                           ///< thread that listens for new connections
+  SocketInterface* mListeningSocket;                      ///< socket used to listen for new connections
+  boost::mutex mClientListMutex;                          ///< mutex
+  boost::condition_variable mClientCountUpdated;          ///< used to say the client count has changed
+  unsigned int mClientUniqueId;                           ///< increments for every client connection
+  unsigned int mClientCount;                              ///< client count
+  bool mLogFunctionInstalled;                             ///< whether the log function is installed
+
+};
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+#endif //__DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_SERVER_H__
index 79cf214..8b9f9ee 100644 (file)
@@ -38,18 +38,31 @@ PerformanceServer::PerformanceServer( AdaptorInternalServices& adaptorServices,
 :mPlatformAbstraction( adaptorServices.GetPlatformAbstractionInterface() ),
  mEnvironmentOptions( environmentOptions ),
  mKernelTrace( adaptorServices.GetKernelTraceInterface() ),
+ mNetworkServer( adaptorServices, environmentOptions ),
  mStatContextManager( *this ),
  mStatisticsLogBitmask( 0 ),
+ mNetworkControlEnabled( mEnvironmentOptions.GetNetworkControlMode()),
  mLoggingEnabled( false ),
  mLogFunctionInstalled( false )
 {
   SetLogging( mEnvironmentOptions.GetPerformanceStatsLoggingOptions(),
               mEnvironmentOptions.GetPerformanceTimeStampOutput(),
               mEnvironmentOptions.GetPerformanceStatsLoggingFrequency());
+
+  if( mNetworkControlEnabled )
+  {
+    mLoggingEnabled  = true;
+    mNetworkServer.Start();
+  }
 }
 
 PerformanceServer::~PerformanceServer()
 {
+  if( mNetworkControlEnabled )
+  {
+    mNetworkServer.Stop();
+  }
+
   if( mLogFunctionInstalled )
   {
     mEnvironmentOptions.UnInstallLogFunction();
@@ -60,18 +73,19 @@ void PerformanceServer::SetLogging( unsigned int statisticsLogOptions,
                                     unsigned int timeStampOutput,
                                     unsigned int logFrequency )
 {
-  if( ( statisticsLogOptions == 0) && ( timeStampOutput == 0 ))
-  {
-    mLoggingEnabled = false;
-    return;
-  }
-
   mStatisticsLogBitmask = statisticsLogOptions;
   mPerformanceOutputBitmask = timeStampOutput;
 
   mStatContextManager.SetLoggingLevel( mStatisticsLogBitmask, logFrequency);
 
-  mLoggingEnabled = true;
+  if( ( mStatisticsLogBitmask == 0) && ( mPerformanceOutputBitmask == 0 ))
+  {
+    mLoggingEnabled = false;
+  }
+  else
+  {
+    mLoggingEnabled = true;
+  }
 }
 
 void PerformanceServer::SetLoggingFrequency( unsigned int logFrequency, ContextId contextId )
@@ -174,8 +188,11 @@ void PerformanceServer::LogContextStatistics( const char* const text )
 
 void PerformanceServer::LogMarker( const PerformanceMarker& marker, const char* const description )
 {
-
-
+  // log to the network ( this is thread safe)
+  if( mNetworkControlEnabled )
+  {
+    mNetworkServer.TransmitMarker( marker, description );
+  }
 
   // log to kernel trace
   if( mPerformanceOutputBitmask & OUTPUT_KERNEL_TRACE )
index 40a495e..9965270 100644 (file)
  *
  */
 
-// EXTERNAL INCLUDES
-#include <boost/thread/mutex.hpp>
+// EXTERNAL INCLDUES
 #include <dali/public-api/common/dali-vector.h>
 
 // INTERNAL INCLUDES
 #include <base/performance-logging/frame-time-stats.h>
+#include <base/performance-logging/networking/network-performance-server.h>
 #include <base/interfaces/adaptor-internal-services.h>
 #include <base/performance-logging/performance-marker.h>
 #include <base/performance-logging/statistics/stat-context-manager.h>
@@ -120,9 +120,11 @@ private:
   const EnvironmentOptions& mEnvironmentOptions;          ///< environment options
   KernelTraceInterface& mKernelTrace;                     ///< kernel trace interface
   boost::mutex mDataMutex;                                ///< mutex
+  NetworkPerformanceServer mNetworkServer;                ///< network server
   StatContextManager mStatContextManager;                 ///< Stat context manager
   unsigned int mStatisticsLogBitmask;                     ///< statistics log level
   unsigned int mPerformanceOutputBitmask;                 ///< performance marker output
+  bool mNetworkControlEnabled:1;                          ///< Whether network control is enabled
   bool mLoggingEnabled:1;                                 ///< whether logging update / render to a log is enabled
   bool mLogFunctionInstalled:1;                           ///< whether the log function is installed
 };
index aeb8e3b..ecaa1e2 100644 (file)
@@ -131,14 +131,14 @@ void Adaptor::ParseEnvironmentOptions()
   unsigned int logPerformanceStats = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE_STATS, 0 );
   unsigned int logPerformanceStatsFrequency = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE_STATS_FREQUENCY, 0 );
   unsigned int performanceTimeStampOutput= GetIntegerEnvironmentVariable( DALI_ENV_PERFORMANCE_TIMESTAMP_OUTPUT, 0 );
-
+  unsigned int networkControl= GetIntegerEnvironmentVariable( DALI_ENV_NETWORK_CONTROL, 0 );
 
   unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
 
   // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
   Dali::Integration::Log::LogFunction  logFunction(Dali::TizenPlatform::LogMessage);
 
-  mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceStats, logPerformanceStatsFrequency, performanceTimeStampOutput, logPanGesture );
+  mEnvironmentOptions.SetLogOptions( logFunction, networkControl, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceStats, logPerformanceStatsFrequency, performanceTimeStampOutput, logPanGesture );
 
   int predictionMode;
   if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
@@ -702,6 +702,12 @@ TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
 {
   return mTriggerEventFactory;
 }
+
+SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
+{
+  return mSocketFactory;
+}
+
 RenderSurface* Adaptor::GetRenderSurfaceInterface()
 {
   return mSurface;
index 63b3463..036dc92 100644 (file)
@@ -42,6 +42,7 @@
 #include <window-visibility-observer.h>
 #include <kernel-trace.h>
 #include <trigger-event-factory.h>
+#include <networking/socket-factory.h>
 
 namespace Dali
 {
@@ -325,6 +326,11 @@ public:  //AdaptorInternalServices
   virtual TriggerEventFactoryInterface& GetTriggerEventFactoryInterface();
 
   /**
+   * @copydoc Dali::Internal::Adaptor::AdaptorInternalServices::GetSocketFactoryInterface()
+   */
+  virtual SocketFactoryInterface& GetSocketFactoryInterface();
+
+  /**
    * @copydoc Dali::Internal::Adaptor::AdaptorInternalServices::GetRenderSurfaceInterface()
    */
   virtual RenderSurface* GetRenderSurfaceInterface();
@@ -524,6 +530,7 @@ private: // Data
   KernelTrace                           mKernelTracer;                ///< Kernel tracer
   TriggerEventFactory                   mTriggerEventFactory;         ///< Trigger event factory
   ObjectProfiler*                       mObjectProfiler;              ///< Tracks object lifetime for profiling
+  SocketFactory                         mSocketFactory;               ///< Socket factory
 public:
   inline static Adaptor& GetImplementation(Dali::Adaptor& adaptor) {return *adaptor.mImpl;}
 };
index bd2c5a9..c495e49 100644 (file)
@@ -41,6 +41,9 @@ adaptor_common_internal_src_files = \
   $(adaptor_common_dir)/events/pinch-gesture-detector.cpp \
   $(adaptor_common_dir)/events/tap-gesture-detector.cpp \
   \
+ $(adaptor_common_dir)/networking/socket-impl.cpp \
+  $(adaptor_common_dir)/networking/socket-factory.cpp \
+  \
   $(adaptor_common_dir)/feedback/feedback-controller.cpp \
   $(adaptor_common_dir)/feedback/feedback-plugin-proxy.cpp \
   \
diff --git a/adaptors/common/networking/socket-factory.cpp b/adaptors/common/networking/socket-factory.cpp
new file mode 100644 (file)
index 0000000..30a2615
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+// CLASS HEADER
+#include "socket-factory.h"
+
+// INTERNAL INCLUDES
+#include <networking/socket-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+SocketInterface* SocketFactory::NewSocket( SocketInterface::Protocol protocol  )
+{
+  return new Socket( protocol );
+}
+
+void SocketFactory::DestroySocket( SocketInterface* socketInterface )
+{
+  Socket* socket( static_cast<Socket* >( socketInterface ));
+  delete socket;
+}
+
+} // Adaptor
+
+} // Internal
+
+} // Dali
diff --git a/adaptors/common/networking/socket-factory.h b/adaptors/common/networking/socket-factory.h
new file mode 100644 (file)
index 0000000..735d724
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_SOCKET_FACTORY_H__
+#define __DALI_INTERNAL_ADAPTOR_SOCKET_FACTORY_H__
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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 <base/interfaces/socket-factory-interface.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * @brief concrete implementation of the socket factory interface
+ */
+class SocketFactory : public SocketFactoryInterface
+{
+public:
+
+
+  /**
+   * @brief Constructor
+   */
+  SocketFactory( )
+  {
+  }
+
+  /**
+   * @brief destructor
+   */
+  virtual ~SocketFactory()
+  {
+  }
+
+  /**
+   * @copydoc SocketFactoryInterface::NewSocket()
+   */
+  virtual SocketInterface* NewSocket( SocketInterface::Protocol protocol  );
+
+  /**
+   * @copydoc SocketFactoryInterface::DestroySocket()
+   */
+  virtual void DestroySocket( SocketInterface* socket  );
+
+};
+
+} // Adaptor
+
+} // Internal
+
+} // Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_SOCKET_FACTORY_H__
diff --git a/adaptors/common/networking/socket-impl.cpp b/adaptors/common/networking/socket-impl.cpp
new file mode 100644 (file)
index 0000000..2a9009d
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ */
+
+// CLASS HEADER
+#include "socket-impl.h"
+
+// EXTERNAL INCLUDES
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dali/integration-api/debug.h>
+
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+
+namespace
+{
+const unsigned int MAX_SOCKET_DATA_WRITE_SIZE = 1024 * 1024 * 10 ; // limit maximum size to write to 10 MB
+}
+
+Socket::Socket( Protocol protocol , int fileDescriptor )
+:mSocketFileDescriptor( fileDescriptor ),
+ mBound(false),
+ mListening(false),
+ mQuitPipeCreated(false),
+ mBlocked(false)
+{
+  int addressFamily( AF_INET );
+  int netProtocol( IPPROTO_TCP );
+  int type( SOCK_STREAM );    // for TCP
+
+  if( protocol == UDP )
+  {
+    type = SOCK_DGRAM;
+    netProtocol = IPPROTO_UDP;
+  }
+  if( mSocketFileDescriptor == -1)
+  {
+    mSocketFileDescriptor = socket( addressFamily,type, netProtocol);
+  }
+  else
+  {
+    // socket already open
+    mBound = true;
+  }
+}
+
+Socket::~Socket()
+{
+  if( SocketIsOpen() )
+  {
+    CloseSocket();
+  }
+}
+
+bool Socket::SocketIsOpen() const
+{
+  return (mSocketFileDescriptor != -1);
+}
+
+bool Socket::CloseSocket()
+{
+
+  if( ! SocketIsOpen() )
+  {
+    DALI_LOG_ERROR("Socket already closed or is invalid \n");
+    return false;
+  }
+
+  int ret = close( mSocketFileDescriptor );
+  mSocketFileDescriptor = -1;
+  mListening = false;
+  mBound = false;
+
+  if( ret == -1 )
+  {
+    DALI_LOG_ERROR("Socket close failed");
+    return false;
+  }
+  return true;
+}
+
+bool Socket::Bind( uint16_t port )
+{
+  if( ! SocketIsOpen() || mBound )
+  {
+     DALI_LOG_ERROR("Socket is invalid, or already bound");
+     return false;
+  }
+  struct sockaddr_in serverAddress;
+
+  memset( &serverAddress, 0, sizeof(serverAddress) );
+  serverAddress.sin_family = AF_INET;                             // internet
+  serverAddress.sin_port = htons( port );  //  host-to-net short (16-bit) translation
+  serverAddress.sin_addr.s_addr = htonl( INADDR_ANY ); //  binds the socket to all available interfaces
+
+  int ret = bind( mSocketFileDescriptor,
+                  (struct sockaddr* ) &serverAddress,
+                  sizeof(serverAddress));
+
+  if( ret == -1 )
+  {
+    DALI_LOG_ERROR("bind failed for port %d %s \n", port, strerror(errno) );
+    return false;
+  }
+
+  mBound = true;
+
+  return true;
+}
+
+bool Socket::Listen( int blacklog)
+{
+  if( ! mBound || mListening )
+  {
+    DALI_LOG_ERROR("socket is not bound, or already opened for listening");
+    return false;
+  }
+  int ret =  listen( mSocketFileDescriptor, blacklog);
+
+  if( ret == -1 )
+  {
+    DALI_LOG_ERROR("Listen failed");
+    return false;
+  }
+
+  mListening = true;
+
+  return true;
+}
+
+SocketInterface* Socket::Accept() const
+{
+  if( !mListening )
+  {
+    DALI_LOG_ERROR("socket is not being listened to");
+    return NULL;
+  }
+
+  struct sockaddr clientAddress;
+
+  socklen_t addressLength(sizeof(sockaddr_in));
+
+  int clientFileDescriptor = accept( mSocketFileDescriptor, &clientAddress, &addressLength);
+  if( clientFileDescriptor == -1 )
+  {
+     DALI_LOG_ERROR("Accept failed");
+     return NULL;
+  }
+
+  // create a new socket, only TCP supports connections
+  Socket* client = new Socket( TCP, clientFileDescriptor );
+
+  return client;
+}
+
+bool Socket::CreateQuitPipe()
+{
+  if( !mQuitPipeCreated )
+  {
+    // create a pipe file descriptor to be able to break from the Select statement
+    //
+    int ret = pipe( mQuitPipe );
+    if( ret != 0)
+    {
+      DALI_LOG_ERROR("Pipe creation failed");
+      return false;
+    }
+    mQuitPipeCreated = true;
+  }
+  return true;
+}
+void Socket::DeleteQuitPipe()
+{
+  if( mQuitPipeCreated )
+  {
+    close( mQuitPipe[0] );
+    close( mQuitPipe[1] );
+  }
+}
+
+SocketInterface::SelectReturn Socket::Select()
+{
+  bool ok = CreateQuitPipe();
+  if( !ok )
+  {
+    return ERROR;
+  }
+
+  fd_set  readFileDescriptors, exceptFileDescriptors;
+  FD_ZERO(&readFileDescriptors);
+  FD_ZERO(&exceptFileDescriptors);
+
+  FD_SET(mSocketFileDescriptor,&readFileDescriptors );
+  FD_SET(mQuitPipe[0],&readFileDescriptors );
+
+  FD_SET(mSocketFileDescriptor,&exceptFileDescriptors);
+
+  unsigned int maxFd = mQuitPipe[0] > mSocketFileDescriptor ? mQuitPipe[0]: mSocketFileDescriptor;
+
+  for( ;; )
+  {
+    // this will block waiting for file descriptors
+    int ret = select( maxFd+1, &readFileDescriptors, NULL, &exceptFileDescriptors, NULL );
+    if( ret == -1 )
+    {
+      DALI_LOG_ERROR("select failed");
+      return ERROR;
+    }
+    else if ( FD_ISSET( mQuitPipe[0] , &readFileDescriptors ))
+    {
+      // ExitSelect() called
+      return QUIT;
+    }
+    else if ( FD_ISSET( mSocketFileDescriptor, &readFileDescriptors ))
+    {
+      // socket data received
+      return DATA_AVAILABLE;
+    }
+  }
+  return QUIT;
+}
+
+void Socket::ExitSelect()
+{
+  if( mQuitPipeCreated )
+  {
+    // write a single character to the pipe (can be anything)
+    char c = ' ';
+    int ret = write( mQuitPipe[1], &c, 1);
+    if( ret < 1 )
+    {
+      DALI_LOG_ERROR("ExitSelect failed!\n");
+    }
+    return;
+  }
+}
+
+bool Socket::ReuseAddress( bool reUse  )
+{
+  if( ! SocketIsOpen() | mBound )
+  {
+    DALI_LOG_ERROR("Socket is invalid or already bound \n");
+    return false;
+  }
+
+  int reUseInteger = reUse; // convert it to an int
+
+  int ret = setsockopt( mSocketFileDescriptor, SOL_SOCKET, SO_REUSEADDR, &reUseInteger, sizeof(reUseInteger));
+  if( ret == -1 )
+  {
+    DALI_LOG_ERROR("SO_REUSEADDR option failed %s \n",strerror(errno));
+    return false;
+  }
+  return true;
+}
+
+bool Socket::SetBufferSize( SocketInterface::BufferType type, unsigned int size )
+{
+  if( ! SocketIsOpen() || mBound )
+  {
+    DALI_LOG_ERROR("Socket is invalid or already bound \n");
+    return false;
+  }
+  int option = SO_RCVBUF;
+  if( type == SocketInterface::SEND_BUFFER )
+  {
+    option = SO_SNDBUF;
+  }
+
+  int ret = setsockopt( mSocketFileDescriptor, SOL_SOCKET,option,&size,sizeof(size));
+  if( ret == -1 )
+  {
+    DALI_LOG_ERROR("SO_RCVBUF / SO_SNDBUF  option failed \n");
+    return false;
+  }
+  return true;
+}
+
+bool Socket::Read( void* buffer, unsigned int bufferSizeInBytes, unsigned int& bytesRead )
+{
+  bytesRead = 0;
+
+  if( !SocketIsOpen() )
+  {
+    DALI_LOG_ERROR("Socket is invalid \n");
+    return false;
+  }
+
+  bytesRead = read( mSocketFileDescriptor, buffer, bufferSizeInBytes );
+
+  return true;
+}
+
+bool Socket::Write( const void* buffer, unsigned int bufferSizeInBytes )
+{
+  if( !SocketIsOpen() )
+  {
+    DALI_LOG_ERROR("Socket is invalid \n");
+    return false;
+  }
+
+  // check we don't try to write more than 10MB ( this can be increased if required)
+  if( bufferSizeInBytes > MAX_SOCKET_DATA_WRITE_SIZE )
+  {
+    DALI_LOG_ERROR("Writing %d bytes exceeds MAX_SOCKET_DATA_WRITE_SIZE of %d bytes \n", bufferSizeInBytes, MAX_SOCKET_DATA_WRITE_SIZE);
+    return false;
+  }
+
+  int bytesWritten = 0;
+
+  // write isn't guaranteed to write the entire buffer in one go
+
+  while(  bytesWritten != static_cast< int>(bufferSizeInBytes))
+  {
+    const char* byteBuffer = static_cast<const char *>( buffer );
+    byteBuffer+=bytesWritten;
+
+    int ret = write( mSocketFileDescriptor, byteBuffer, bufferSizeInBytes - bytesWritten );
+    if( ret < 1)
+    {
+      DALI_LOG_ERROR("Socket writer error \n");
+      return false;
+    }
+    else
+    {
+      bytesWritten += ret;
+    }
+  }
+  return true;
+}
+
+} // Adaptor
+} // Internal
+} // Dali
+
diff --git a/adaptors/common/networking/socket-impl.h b/adaptors/common/networking/socket-impl.h
new file mode 100644 (file)
index 0000000..016127a
--- /dev/null
@@ -0,0 +1,138 @@
+#ifndef __DALI_INTERNAL_ADAPTOR_SOCKET_IMPL_H__
+#define __DALI_INTERNAL_ADAPTOR_SOCKET_IMPL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed 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 <base/interfaces/socket-interface.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * @brief Concrete implementation of a socket under Linux.
+ *
+ * Provides automatic closing of socket on destruction.
+ */
+class Socket : public SocketInterface
+{
+public:
+
+  /**
+   * @brief Constructor
+   * @param protocol network protocol
+   * @param fileDescriptor option file descriptor if the socket is already open
+   */
+  Socket( Protocol protocol , int fileDescriptor = -1 );
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketIsOpen()
+   */
+  virtual bool SocketIsOpen() const;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::CloseSocket
+   */
+  virtual bool CloseSocket();
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::Bind
+   */
+  virtual bool Bind( uint16_t port ) ;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::Listen
+   */
+  virtual bool Listen( int blacklog);
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::Accept
+   */
+  virtual SocketInterface* Accept() const ;
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::Select
+   */
+  virtual SelectReturn Select( );
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::ExitSelect
+   */
+  virtual void ExitSelect();
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::Recieve
+   */
+  virtual bool Read( void* buffer, unsigned int bufferSizeInBytes, unsigned int& bytesRead );
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::Send
+   */
+  virtual bool Write( const void* buffer, unsigned int bufferLength );
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::ReuseAddress
+   */
+  virtual bool ReuseAddress( bool reUse );
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::SocketInterface::SetBufferSize
+   *
+   */
+  virtual bool SetBufferSize( SocketInterface::BufferType type, unsigned int bufferSizeInBytes );
+
+  /**
+   * @brief Virtual destructor
+   */
+  virtual ~Socket();
+
+private:
+
+
+  /**
+   * @brief Helper to create the quit pipe
+   */
+  bool CreateQuitPipe();
+
+  /**
+   * @brief  Helper to delete the quit pipe
+   */
+  void DeleteQuitPipe();
+
+  int mSocketFileDescriptor; ///< file descriptor
+  int mQuitPipe[2];          ///< Pipe to inform Select to quit.
+  bool mBound:1;             ///< whether the socket is bound
+  bool mListening:1;         ///< whether the socket is being listen to
+  bool mQuitPipeCreated:1;   ///< whether the quit pipe has been created
+  bool mBlocked:1;           ///< whether the socket is blocked waiting for a connection
+};
+
+
+
+} // Adaptor
+
+} // Internal
+
+} // Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_SOCKET_IMPL_H__