Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/CMakeLists.txt
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/CMakeLists.txt	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/CMakeLists.txt	(revision 4941)
@@ -0,0 +1,36 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+
+PROJECT(rtnet_sdo_example)
+
+SET( ${PROJECT_NAME}_MAJOR_VERSION 1 )
+SET( ${PROJECT_NAME}_MINOR_VERSION 0 )
+SET( ${PROJECT_NAME}_PATCH_LEVEL 0 )
+
+ADD_DEFINITIONS(-DHAVE_NETINET_IN_H -DHAVE_INTTYPES_H)
+
+INCLUDE_DIRECTORIES(.)
+
+ADD_SUBDIRECTORY(common)
+
+INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}
+                    /usr/include/boost
+                    /usr/local/include/thrift)
+
+ADD_EXECUTABLE(rtnet_sdo_example
+               rtnet_sdo_example.cpp
+               Client.cpp Client.h
+               RtnetDataHandler.cpp RtnetDataHandler.h
+               RtnetDataRequest.cpp RtnetDataRequest.h
+               RtnetDataListener.cpp RtnetDataListener.h
+               ConnectionRequiredRunnable.cpp ConnectionRequiredRunnable.h
+               ConnectionStatusMonitor.cpp ConnectionStatusMonitor.h
+              )
+TARGET_LINK_LIBRARIES(rtnet_sdo_example lib_gpssthrift thrift rt ssl z pthread)
+
+INSTALL(TARGETS rtnet_sdo_example DESTINATION bin PERMISSIONS
+  OWNER_READ OWNER_WRITE OWNER_EXECUTE
+  GROUP_READ GROUP_EXECUTE
+  WORLD_READ WORLD_EXECUTE
+)
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/Client.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/Client.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/Client.cpp	(revision 4941)
@@ -0,0 +1,54 @@
+#include "Client.h"
+#include "ConnectionStatusMonitor.h"
+#include "RtnetDataHandler.h"
+#include "RtnetDataListener.h"
+#include "RtnetDataRequest.h"
+
+#include <transport/TSocket.h>
+#include <protocol/TBinaryProtocol.h>
+
+#include <cstdio>
+
+using boost::shared_ptr;
+
+using namespace apache::thrift;
+using namespace apache::thrift::protocol;
+using namespace apache::thrift::transport;
+using namespace apache::thrift::concurrency;
+
+Client::Client(const std::string& server,
+               int16_t port, boost::shared_ptr<TimerManager>& timeMgr,
+               boost::shared_ptr<RtnetDataHandler> dataHandler)
+      : connectionMonitor_(),
+        transport_(),
+        protocol_(),
+        sender_(),
+        senderThread_(),
+        receiver_(),
+        receiverThread_()
+{
+  transport_ = boost::shared_ptr<TTransport>(new TSocket(server, port));
+  protocol_ = boost::shared_ptr<TProtocol>(new TBinaryProtocol(transport_));
+ 
+  connectionMonitor_ = boost::shared_ptr<ConnectionStatusMonitor>(new ConnectionStatusMonitor(transport_,timeMgr));
+ 
+  sender_ = boost::shared_ptr<ConnectionRequiredRunnable>(new RtnetDataRequest(protocol_, connectionMonitor_));
+  connectionMonitor_->addListener(sender_);
+  senderThread_ = timeMgr->threadFactory()->newThread(sender_);
+  senderThread_->start();
+  receiver_ = boost::shared_ptr<ConnectionRequiredRunnable>(new RtnetDataListener(protocol_, connectionMonitor_, dataHandler));
+  connectionMonitor_->addListener(receiver_);
+  receiverThread_ = timeMgr->threadFactory()->newThread(receiver_);
+  receiverThread_->start();
+ 
+  connectionMonitor_->tryOpen();
+}
+
+Client::~Client() {
+}
+
+void
+Client::stop() {
+  connectionMonitor_->stop();
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/Client.h
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/Client.h	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/Client.h	(revision 4941)
@@ -0,0 +1,33 @@
+#ifndef RTNET_SDO_EXAMPLE_CLIENT_H
+#define RTNET_SDO_EXAMPLE_CLIENT_H
+
+#include <string>
+
+#include <transport/TTransport.h>
+#include <protocol/TProtocol.h>
+#include <concurrency/TimerManager.h>
+
+class RtnetDataHandler;
+class ConnectionRequiredRunnable;
+class ConnectionStatusMonitor;
+
+class Client
+{
+public:
+  Client(const std::string& server, int16_t port,
+         boost::shared_ptr<apache::thrift::concurrency::TimerManager>& timeMgr,
+         boost::shared_ptr<RtnetDataHandler> dataHandler);
+  ~Client();
+  void stop();
+private:
+  boost::shared_ptr<ConnectionStatusMonitor> connectionMonitor_;
+  
+  boost::shared_ptr<apache::thrift::transport::TTransport> transport_;
+  boost::shared_ptr<apache::thrift::protocol::TProtocol> protocol_;
+  boost::shared_ptr<ConnectionRequiredRunnable> sender_;
+  boost::shared_ptr<apache::thrift::concurrency::Thread> senderThread_;
+  boost::shared_ptr<ConnectionRequiredRunnable> receiver_;
+  boost::shared_ptr<apache::thrift::concurrency::Thread> receiverThread_;
+};
+
+#endif // RTNET_SDO_EXAMPLE_CLIENT_H
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionRequiredRunnable.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionRequiredRunnable.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionRequiredRunnable.cpp	(revision 4941)
@@ -0,0 +1,54 @@
+#include "ConnectionRequiredRunnable.h"
+
+using namespace apache::thrift::concurrency;
+using std::string;
+
+ConnectionRequiredRunnable::ConnectionRequiredRunnable(boost::shared_ptr<ConnectionStatusMonitor>& connectionMonitor, const string& name)
+                          : connectionMonitor_(connectionMonitor),
+                            threadName_(name),
+                            connectMonitor_(),
+                            disconnectMonitor_(),
+                            stop_(false)
+{
+}
+
+void
+ConnectionRequiredRunnable::connectionLost()
+{
+}
+
+void
+ConnectionRequiredRunnable::connectionEstablished()
+{
+  connectMonitor_.notifyAll();
+}
+
+void
+ConnectionRequiredRunnable::disconnected()
+{
+  connectionMonitor_->disconnected(this);
+  disconnectMonitor_.notifyAll();
+}
+
+void
+ConnectionRequiredRunnable::connectWait()
+{
+  if (connectionMonitor_->connected()) return;
+  connectMonitor_.waitForever();
+}
+
+void
+ConnectionRequiredRunnable::disconnectWait()
+{
+  if (!connectionMonitor_->connected()) return;
+  disconnectMonitor_.waitForever();
+}
+
+void
+ConnectionRequiredRunnable::stop()
+{
+  stop_ = true;
+  connectMonitor_.notifyAll();
+  disconnectMonitor_.notifyAll();
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionRequiredRunnable.h
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionRequiredRunnable.h	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionRequiredRunnable.h	(revision 4941)
@@ -0,0 +1,29 @@
+#ifndef RTNET_SDO_EXAMPLE_CONNECTIONREQUIREDRUNNABLE_H
+#define RTNET_SDO_EXAMPLE_CONNECTIONREQUIREDRUNNABLE_H
+
+#include <concurrency/Thread.h>
+#include <concurrency/Monitor.h>
+#include <string>
+
+#include "ConnectionStatusMonitor.h"
+
+class ConnectionRequiredRunnable : public apache::thrift::concurrency::Runnable
+{
+public:
+  ConnectionRequiredRunnable(boost::shared_ptr<ConnectionStatusMonitor>& connectionMonitor, const std::string& name);
+  virtual ~ConnectionRequiredRunnable() {}
+  virtual void connectionLost();
+  virtual void connectionEstablished();
+  virtual void stop();
+protected:
+  virtual void disconnected();
+  virtual void connectWait();
+  virtual void disconnectWait();
+  boost::shared_ptr<ConnectionStatusMonitor> connectionMonitor_;
+  std::string threadName_;
+  apache::thrift::concurrency::Monitor connectMonitor_;
+  apache::thrift::concurrency::Monitor disconnectMonitor_;
+  bool stop_;
+};
+
+#endif // RTNET_PLOT_CONNECTIONREQUIREDRUNNABLE_H
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionStatusMonitor.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionStatusMonitor.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionStatusMonitor.cpp	(revision 4941)
@@ -0,0 +1,86 @@
+#include "ConnectionStatusMonitor.h"
+#include "ConnectionRequiredRunnable.h"
+
+#include <cstdio>
+
+using namespace apache::thrift::transport;
+using namespace apache::thrift::concurrency;
+
+ConnectionStatusMonitor::ConnectionStatusMonitor(boost::shared_ptr<TTransport>& transport,
+                                                 boost::shared_ptr<TimerManager>& timeMgr)
+                       : listeners_(),
+                         transport_(transport),
+                         timeMgr_(timeMgr),
+                         connected_(0)
+{
+}
+
+ConnectionStatusMonitor::~ConnectionStatusMonitor() {
+}
+
+void
+ConnectionStatusMonitor::addListener(boost::shared_ptr<ConnectionRequiredRunnable> listener) {
+  listeners_.insert(listener);
+}
+
+bool
+ConnectionStatusMonitor::connected() {
+  return (((long)connected_ == 0) ? false : true);
+  //return connected_.load(); // if using C++0x
+}
+
+void
+ConnectionStatusMonitor::disconnected(const ConnectionRequiredRunnable* noticer) {
+  bool expected=true;
+  if ((long)connected_ != 0) {
+  //if (connected_.compare_exchange_strong(expected,false)) // if using C++0x
+    --connected_;
+    std::set<boost::shared_ptr<ConnectionRequiredRunnable> >::iterator listener;
+    for (listener=listeners_.begin(); listener != listeners_.end(); ++listener) {
+    //for (auto listener=listeners_.begin(); listener != listeners_.end(); ++listener) // if using C++0x
+      // The thread running the noticer is our current execution thread. If we
+      // notify it it'll block and we'll be deadlocked. Since it noticed the
+      // disconnect it is responsible for initiating its own wait state.
+      if (listener->get() == noticer) continue;
+      (*listener)->connectionLost();
+    }
+  }
+  // Try to reconnect in five seconds
+  timeMgr_->add(boost::shared_ptr<Runnable>(new Reconnect(this)), 5 * 1000);
+}
+
+void
+ConnectionStatusMonitor::tryOpen() {
+  if ((long)connected_ != 0)
+  //if (connected_.load()) // if using C++0x
+    return;
+  
+  // make sure it's closed
+  transport_->close();
+  try {
+    transport_->open();
+    ++connected_;
+    //connected_.store(true); // if using C++0x
+    std::set<boost::shared_ptr<ConnectionRequiredRunnable> >::iterator listener;
+    for (listener=listeners_.begin(); listener != listeners_.end(); ++listener) {
+    //for (auto listener = listeners_.begin(); listener != listeners_.end(); ++listener) { // if using C++0x
+      (*listener)->connectionEstablished();
+    }
+    return;
+  } catch (TTransportException& e) {
+    fprintf(stderr,"opening transport failed\n");
+  }
+  // Try to reconnect in five seconds
+  timeMgr_->add(boost::shared_ptr<Runnable>(new Reconnect(this)), 5 * 1000);
+}
+
+void
+ConnectionStatusMonitor::stop() {
+  std::set<boost::shared_ptr<ConnectionRequiredRunnable> >::iterator listener;
+  for (listener=listeners_.begin(); listener != listeners_.end(); ++listener) {
+  //for (auto listener = listeners_.begin(); listener != listeners_.end(); ++listener) // if using C++0x
+    (*listener)->stop();
+  }
+  listeners_.clear();
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionStatusMonitor.h
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionStatusMonitor.h	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/ConnectionStatusMonitor.h	(revision 4941)
@@ -0,0 +1,46 @@
+#ifndef RTNET_SDO_EXAMPLE_CONNECTIONSTATUSMONITOR_H
+#define RTNET_SDO_EXAMPLE_CONNECTIONSTATUSMONITOR_H
+
+#include <transport/TTransport.h>
+#include <concurrency/TimerManager.h>
+
+#include <set>
+//#include <cstdatomic> // needs newer version of g++ using C++0x
+#include <boost/detail/atomic_count.hpp>
+
+class ConnectionRequiredRunnable;
+
+class ConnectionStatusMonitor
+{
+public:
+  ConnectionStatusMonitor(boost::shared_ptr<apache::thrift::transport::TTransport>& transport,
+                          boost::shared_ptr<apache::thrift::concurrency::TimerManager>& timeMgr);
+  ~ConnectionStatusMonitor();
+
+  void addListener(boost::shared_ptr<ConnectionRequiredRunnable> listener);
+  void disconnected(const ConnectionRequiredRunnable* noticer);
+  void tryOpen();
+  void stop();
+  bool connected();
+
+private:
+  class Reconnect : public apache::thrift::concurrency::Runnable
+  {
+  public:
+    Reconnect(ConnectionStatusMonitor* parent) : parent_(parent) {}
+    void run() {
+      parent_->tryOpen();
+    }
+  private:
+    ConnectionStatusMonitor* parent_;
+  };
+  std::set<boost::shared_ptr<ConnectionRequiredRunnable> > listeners_;
+  boost::shared_ptr<apache::thrift::transport::TTransport> transport_;
+  boost::shared_ptr<apache::thrift::concurrency::TimerManager> timeMgr_;
+  boost::shared_ptr<apache::thrift::concurrency::ThreadFactory> thFactory_;
+  //std::atomic<bool> connected_;
+  //boost::atomic<bool> connected_; // need a higher version of boost or gcc than is available on kurenai
+  boost::detail::atomic_count connected_; // need a higher version of boost or gcc than is available on kurenai
+};
+
+#endif // RTNET_SDO_EXAMPLE_CONNECTIONSTATUSMONITOR_H
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataHandler.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataHandler.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataHandler.cpp	(revision 4941)
@@ -0,0 +1,94 @@
+#include "RtnetDataHandler.h"
+
+#include <cstdio>
+
+extern "C" {
+#include <time.h>
+}
+
+using namespace com::gpssolutions::rtnet;
+
+RtnetDataHandler::RtnetDataHandler()
+{
+}
+
+RtnetDataHandler::~RtnetDataHandler() {
+}
+
+void
+RtnetDataHandler::startDataStream() {
+}
+
+void
+RtnetDataHandler::registerRtnet(const RtnetInformation& info) {
+  /*registered_ = true;
+  jobName_ = info.jobName;
+  printf("registerRtnet(): %s\n",jobName_.c_str());
+  OneRtnetJobInfo* pInfo = jobStatus_->oneJobInfo(jobName_);
+  {
+    Guard lock(pInfo->mutex());
+    UpdateStatus& status = pInfo->updateStatus();
+    status.stationInfoUpdated = 0;
+    status.stationAuxInfoUpdated = 0;
+    status.rtnetInfoUpdated = 0;
+  }*/
+}
+
+void
+RtnetDataHandler::handleZDAmb(const std::vector<ZDAmb> & ambList) {
+  printf("Decoded ZD ambiguity record\n");
+  if (ambList.empty()) {
+    printf("No ZD ambiguities present\n");
+    return;
+  }
+  std::vector<ZDAmb>::const_iterator zdIt;
+  std::string staName = ambList[0].stationID;
+  printf ("Received %zd zero-difference ambiguities for station %s\n",ambList.size(),staName.c_str());
+}
+
+void
+RtnetDataHandler::handleDDAmbresBaselines(const std::vector<DDAmbresBaseline>& ambList) {
+  printf("Decoded double difference ambiguities record (%zd DD ambiguities)\n",ambList.size());
+}
+
+void
+RtnetDataHandler::handleSatelliteXYZ(const std::vector<SatelliteXYZ>& svXYZList) {
+  printf("Decoded satellite XYZ record (%zd satellites)\n",svXYZList.size());
+}
+
+void
+RtnetDataHandler::handleStationInfo(const std::vector<StationInfo> & stationList) {
+  printf("Decoded station information record for %zd stations\n",stationList.size());
+}
+
+void
+RtnetDataHandler::handleStationAuxInfo(const std::vector<StationAuxInfo> & stationAuxList) {
+  printf("Decoded auxilary station record for %d stations\n",stationAuxList.size());
+}
+
+void
+RtnetDataHandler::handleDGPSCorr(const std::vector<DGPSCorr> & dgpsList) {
+  printf("Decoded DGPS correction (%zd corrections)\n",dgpsList.size());
+}
+
+void
+RtnetDataHandler::handleSatelliteClock(const std::vector<SatelliteClock> & svList) {
+  printf("Decoded RTNet satellite clock structure (%zd satellite clocks)\n",svList.size());
+}
+
+void
+RtnetDataHandler::handleEpochResults(const RtnetEpoch& epoch) {
+  long mjlDay = epoch.mjlDay;
+  if (mjlDay < 0) mjlDay += 65536l;
+  long unixSec = (mjlDay-40587L)*24L*60L*60L;
+  unixSec += epoch.msecDay / 1000;
+  char timeStrBuffer[18];
+  struct tm tmEpoch;
+  time_t tEpoch = static_cast<time_t>(unixSec);
+  gmtime_r(&tEpoch,&tmEpoch);
+  if (strftime(timeStrBuffer,17,"%H:%M:%S",&tmEpoch) != 0)
+    printf("Decoded RTNet epoch structure for epoch %s.%03d\n",timeStrBuffer,epoch.msecDay % 1000);
+  else
+    printf("Decoded RTNet epoch structure for epoch %ld %.3f\n",epoch.mjlDay,epoch.msecDay / 1000.0);
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataHandler.h
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataHandler.h	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataHandler.h	(revision 4941)
@@ -0,0 +1,23 @@
+#ifndef RTNET_SDO_EXAMPLE_RTNETDATAHANDLER_H
+#define RTNET_SDO_EXAMPLE_RTNETDATAHANDLER_H
+
+#include "common/thrift/RtnetData.h"
+
+class RtnetDataHandler : public com::gpssolutions::rtnet::RtnetDataIf
+{
+public:
+  RtnetDataHandler();
+  ~RtnetDataHandler();
+  void startDataStream();
+  void registerRtnet(const  ::com::gpssolutions::rtnet::RtnetInformation& info);
+  void handleZDAmb(const std::vector< ::com::gpssolutions::rtnet::ZDAmb> & ambList);
+  void handleDDAmbresBaselines(const std::vector< ::com::gpssolutions::rtnet::DDAmbresBaseline>& ambList);
+  void handleSatelliteXYZ(const std::vector< ::com::gpssolutions::rtnet::SatelliteXYZ>& svXYZList);
+  void handleStationInfo(const std::vector< ::com::gpssolutions::rtnet::StationInfo> & stationList);
+  void handleStationAuxInfo(const std::vector< ::com::gpssolutions::rtnet::StationAuxInfo> & stationAuxList);
+  void handleDGPSCorr(const std::vector< ::com::gpssolutions::rtnet::DGPSCorr> & dgpsList);
+  void handleSatelliteClock(const std::vector< ::com::gpssolutions::rtnet::SatelliteClock> & svList);
+  void handleEpochResults(const  ::com::gpssolutions::rtnet::RtnetEpoch& epoch);
+};
+
+#endif // RTNET_SDO_EXAMPLE_RTNETDATAHANDLER_H
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataListener.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataListener.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataListener.cpp	(revision 4941)
@@ -0,0 +1,53 @@
+#include "RtnetDataListener.h"
+
+#include <cstdio>
+
+using namespace apache::thrift;
+using namespace apache::thrift::protocol;
+using namespace com::gpssolutions::rtnet;
+
+RtnetDataListener::RtnetDataListener(boost::shared_ptr<TProtocol>& protocol,
+                                     boost::shared_ptr<ConnectionStatusMonitor>& connectionMonitor,
+                                     boost::shared_ptr<com::gpssolutions::rtnet::RtnetDataIf> dataHandler)
+                 : ConnectionRequiredRunnable(connectionMonitor,"StreamDataRequestService"),
+                   dataHandler_(dataHandler),
+                   protocol_(protocol),
+                   processor_()
+{
+  processor_ = boost::shared_ptr<RtnetDataProcessor>(new RtnetDataProcessor(dataHandler_));
+}
+
+RtnetDataListener::~RtnetDataListener() {
+}
+
+void
+RtnetDataListener::run() {
+  printf("Starting RtnetDataListener thread.\n");
+  while (!stop_) {
+    printf("RtnetDataListener::waiting for connection\n");
+    connectWait();
+    printf("RtnetDataListener::Connected to rtnet\n");
+    if (stop_) {
+      printf("Quitting RtnetDataListener thread (stop is true)\n");
+      return;
+    }
+    try {
+      while (processor_->process(protocol_,protocol_,0)) {}
+    } catch(TException& e) {
+      fprintf(stderr,"Caught an exception generated by Thrift in RtnetDataListener: %s\n",e.what());
+    } catch(...) {
+      fprintf(stderr,"Unknown exception generated by Thrift in RtnetDataListener\n");
+    }
+    if (!stop_)
+      disconnected();
+  }
+  printf("Quitting RtnetDataListener thread\n");
+}
+
+void
+RtnetDataListener::stop(){
+  printf("RtnetDataListener::stop()\n");
+  protocol_->getTransport()->close();
+  ConnectionRequiredRunnable::stop();
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataListener.h
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataListener.h	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataListener.h	(revision 4941)
@@ -0,0 +1,26 @@
+#ifndef RTNET_SDO_EXAMPLE_RTNETDATALISTENER_H
+#define RTNET_SDO_EXAMPLE_RTNETDATALISTENER_H
+
+#include "ConnectionRequiredRunnable.h"
+#include "RtnetDataHandler.h"
+#include "common/thrift/RtnetData.h"
+
+#include <protocol/TProtocol.h>
+
+class RtnetDataListener : public ConnectionRequiredRunnable
+{
+public:
+  RtnetDataListener(boost::shared_ptr<apache::thrift::protocol::TProtocol>& protocol,
+                    boost::shared_ptr<ConnectionStatusMonitor>& connectionMonitor,
+                    boost::shared_ptr<com::gpssolutions::rtnet::RtnetDataIf> dataHandler);
+  ~RtnetDataListener();
+
+  void run();
+  void stop();
+private:
+  boost::shared_ptr<com::gpssolutions::rtnet::RtnetDataIf> dataHandler_;
+  boost::shared_ptr<apache::thrift::protocol::TProtocol> protocol_;
+  boost::shared_ptr<com::gpssolutions::rtnet::RtnetDataProcessor> processor_;
+};
+
+#endif // RTNET_SDO_EXAMPLE_RTNETDATALISTENER_H
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataRequest.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataRequest.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataRequest.cpp	(revision 4941)
@@ -0,0 +1,37 @@
+#include "RtnetDataRequest.h"
+
+#include <cstdio>
+
+using namespace apache::thrift;
+using namespace apache::thrift::protocol;
+using namespace com::gpssolutions::rtnet;
+
+RtnetDataRequest::RtnetDataRequest(boost::shared_ptr<TProtocol>& protocol,
+                                   boost::shared_ptr<ConnectionStatusMonitor>& connectionMonitor)
+                : ConnectionRequiredRunnable(connectionMonitor,"RtnetDataRequestService"),
+                  client_(new RtnetDataClient(protocol))
+{
+}
+
+void
+RtnetDataRequest::run() {
+  printf("Starting RtnetDataRequest thread.\n");
+  while (!stop_) {
+    printf("waiting for connection\n");
+    connectWait();
+    printf("Connected to rtnet\n");
+    if (stop_) {
+      printf("Quitting RtnetDataRequest thread (stop is true)\n");
+      return;
+    }
+    try {
+      printf("sending request for rtnet data stream\n");
+      client_->startDataStream();
+      disconnectWait();
+    } catch (TException& e) {
+      fprintf(stderr,"Caught an exception generated by Thrift in RtnetDataRequest: %s\n",e.what());
+    }
+  }
+  printf("Quitting RtnetDataRequest thread\n");
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataRequest.h
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataRequest.h	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/RtnetDataRequest.h	(revision 4941)
@@ -0,0 +1,21 @@
+#ifndef RTNET_SDO_EXAMPLE_RTNETDATAREQUEST_H
+#define RTNET_SDO_EXAMPLE_RTNETDATAREQUEST_H
+
+#include "ConnectionRequiredRunnable.h"
+#include "common/thrift/RtnetData.h"
+
+#include <protocol/TProtocol.h>
+
+class RtnetDataRequest : public ConnectionRequiredRunnable
+{
+public:
+  RtnetDataRequest(boost::shared_ptr<apache::thrift::protocol::TProtocol>& protocol,
+                   boost::shared_ptr<ConnectionStatusMonitor>& connectionMonitor);
+  ~RtnetDataRequest() {}
+
+  void run();
+private:
+  boost::shared_ptr<com::gpssolutions::rtnet::RtnetDataClient> client_;
+};
+
+#endif // RTNET_SDO_EXAMPLE_RTNETDATAREQUEST_H
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/common/CMakeLists.txt
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/common/CMakeLists.txt	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/common/CMakeLists.txt	(revision 4941)
@@ -0,0 +1,1 @@
+ADD_SUBDIRECTORY(thrift)
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/common/thrift/CMakeLists.txt
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/common/thrift/CMakeLists.txt	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/common/thrift/CMakeLists.txt	(revision 4941)
@@ -0,0 +1,114 @@
+INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}
+                    ${PROJECT_SOURCE_DIR}/3rd_party ${PROJECT_SOURCE_DIR}/3rd_party/thrift
+                    ${PROJECT_BINARY_DIR}/3rd_party/thrift
+                    )
+
+IF (NOT IS_DIRECTORY ${PROJECT_BINARY_DIR}/common/thrift)
+  FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/common/thrift)
+ENDIF (NOT IS_DIRECTORY ${PROJECT_BINARY_DIR}/common/thrift)
+
+#IF (NOT IS_DIRECTORY ${PROJECT_BINARY_DIR}/thrift_js)
+#  FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/thrift_js)
+#ENDIF (NOT IS_DIRECTORY ${PROJECT_BINARY_DIR}/thrift_js)
+
+#IF (NOT IS_DIRECTORY ${PROJECT_BINARY_DIR}/thrift_perl)
+#  FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/thrift_perl)
+#ENDIF (NOT IS_DIRECTORY ${PROJECT_BINARY_DIR}/thrift_perl)
+
+SET (gpssthrift_sources
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_constants.cpp
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_constants.h
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_types.cpp
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_types.h
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_constants.cpp
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_constants.h
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_types.cpp
+     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_types.h
+#     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_constants.cpp
+#     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_constants.h
+#     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_types.cpp
+#     ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_types.h
+     ${PROJECT_BINARY_DIR}/common/thrift/RtnetData.cpp
+     ${PROJECT_BINARY_DIR}/common/thrift/RtnetData.h
+#     ${PROJECT_BINARY_DIR}/common/thrift/RtnetDataJs.cpp
+#     ${PROJECT_BINARY_DIR}/common/thrift/RtnetDataJs.h
+    )
+
+ADD_LIBRARY(lib_gpssthrift ${gpssthrift_sources})
+# create symbolic lib_codecs target for calling target gpsscodecs
+##ADD_CUSTOM_TARGET( lib_gpssthrift DEPENDS lib_gpssthrift )
+# change lib_target properties
+SET_TARGET_PROPERTIES( lib_gpssthrift PROPERTIES
+  # create *nix style library versions + symbolic links
+  VERSION 1
+  SOVERSION 1
+  # allow creating static and shared libs without conflicts
+  CLEAN_DIRECT_OUTPUT 1
+  # avoid conflicts between library and binary target names
+  OUTPUT_NAME gpssthrift )
+
+INSTALL(TARGETS lib_gpssthrift DESTINATION lib PERMISSIONS
+  OWNER_READ OWNER_WRITE OWNER_EXECUTE
+  GROUP_READ GROUP_EXECUTE
+  WORLD_READ WORLD_EXECUTE
+)
+
+#SET (lib_gpss_js ${PROJECT_BINARY_DIR}/thrift_js/RtnetDataJs.js
+#                 ${PROJECT_BINARY_DIR}/thrift_js/rtnet_data_types.js
+#                 ${PROJECT_BINARY_DIR}/thrift_js/rtnet_js_types.js
+#    )
+
+#INSTALL(FILES ${lib_gpss_js} DESTINATION www PERMISSIONS
+#  OWNER_READ OWNER_WRITE OWNER_READ
+#  GROUP_READ GROUP_READ
+#  WORLD_READ WORLD_READ
+#)
+
+ADD_CUSTOM_COMMAND (
+  OUTPUT ${PROJECT_BINARY_DIR}/common/thrift/rtnet_constants.cpp
+         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_constants.h
+         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_constants.cpp
+         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_constants.h
+         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_types.cpp
+         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_types.h
+         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_types.cpp
+         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_types.h
+         ${PROJECT_BINARY_DIR}/common/thrift/RtnetData.cpp
+         ${PROJECT_BINARY_DIR}/common/thrift/RtnetData.h
+
+  COMMAND cmake -E echo Generating rtnet Thrift code
+  COMMAND cmake -E echo thrift -r --gen cpp --out ${PROJECT_BINARY_DIR}/common/thrift ${PROJECT_SOURCE_DIR}/thrift_template/rtnet.thrift
+  COMMAND thrift --gen cpp -r --out ${PROJECT_BINARY_DIR}/common/thrift ${PROJECT_SOURCE_DIR}/thrift_template/rtnet.thrift
+  # -r (recursive) apparently doesn't work for perl generator
+#  COMMAND cmake -E echo thrift --gen perl --out ${PROJECT_BINARY_DIR}/common/thrift_perl ${PROJECT_SOURCE_DIR}/thrift_template/rtnet.thrift
+#  COMMAND thrift --gen perl --out ${PROJECT_BINARY_DIR}/thrift_perl ${PROJECT_SOURCE_DIR}/thrift_template/rtnet.thrift
+#  COMMAND cmake -E echo thrift --gen perl --out ${PROJECT_BINARY_DIR}/common/thrift_perl ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_data.thrift
+#  COMMAND thrift --gen perl --out ${PROJECT_BINARY_DIR}/thrift_perl ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_data.thrift
+
+  DEPENDS ${PROJECT_SOURCE_DIR}/thrift_template/rtnet.thrift
+          ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_data.thrift
+)
+#ADD_CUSTOM_COMMAND (
+#  OUTPUT ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_constants.cpp
+#         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_constants.h
+#         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_types.cpp
+#         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_js_types.h
+#         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_constants.cpp
+#         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_constants.h
+#         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_types.cpp
+#         ${PROJECT_BINARY_DIR}/common/thrift/rtnet_data_types.h
+#         ${PROJECT_BINARY_DIR}/common/thrift/RtnetDataJs.cpp
+#         ${PROJECT_BINARY_DIR}/common/thrift/RtnetDataJs.h
+#         ${PROJECT_BINARY_DIR}/thrift_js/RtnetDataJs.js
+#         ${PROJECT_BINARY_DIR}/thrift_js/rtnet_data_types.js
+#         ${PROJECT_BINARY_DIR}/thrift_js/rtnet_js_types.js
+
+#  COMMAND cmake -E echo Generating rtnet JavaScript Thrift code
+#  COMMAND cmake -E echo thrift -r --gen cpp --out ${PROJECT_BINARY_DIR}/common/thrift ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_js.thrift
+#  COMMAND thrift -r --gen cpp --out ${PROJECT_BINARY_DIR}/common/thrift ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_js.thrift
+#  COMMAND cmake -E echo thrift -r --gen js:jquery --out ${PROJECT_BINARY_DIR}/thrift_js ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_js.thrift
+#  COMMAND thrift -r --gen js:jquery --out ${PROJECT_BINARY_DIR}/thrift_js ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_js.thrift
+
+#  DEPENDS ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_js.thrift
+#          ${PROJECT_SOURCE_DIR}/thrift_template/rtnet_data.thrift
+#)
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/rtnet_sdo_example.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/rtnet_sdo_example.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/rtnet_sdo_example.cpp	(revision 4941)
@@ -0,0 +1,110 @@
+#include <concurrency/TimerManager.h>
+#include <concurrency/PlatformThreadFactory.h>
+
+#include "Client.h"
+#include "RtnetDataHandler.h"
+
+#include <cstdio>
+#include <cstring>
+extern "C" {
+#include <strings.h>
+#include <sys/signal.h>
+#include <unistd.h>
+}
+
+using namespace apache::thrift::concurrency;
+using namespace com::gpssolutions::rtnet;
+
+volatile int STOP=0;
+void catch_ctrlc(int /*sig_num*/)
+{
+  static int once=0;
+  printf("Caught SIGINT signal, terminating rtnet_sdo_example\n");
+  if (once) exit(-1);
+  once=1;
+  STOP=1;
+}
+
+void usage()
+{
+  printf("rtnet_sdo_example  -H (RTNet host default=localhost)\n");
+  printf("                   -p (RTNet SDO port)\n");
+  printf("                  [-h (show this usage information)]\n");
+}
+
+int main(int argc, char** argv)
+{
+  signal(SIGINT, catch_ctrlc);
+  int ii;
+  bool prevArgSet=false;
+  bool rtnetPortSet=false;
+  enum Argument
+  {
+    RtnetPort,
+    RtnetHost
+  };
+  Argument prevArg=RtnetPort;
+  std::string host;
+  long port=0;
+  long tmpval;
+  char *endptr;
+  for (ii=1; ii < argc; ++ii)
+  {
+    if (prevArgSet)
+    {
+      switch (prevArg)
+      {
+      case RtnetPort:
+        tmpval = strtol(argv[ii],&endptr,10);
+        if (endptr == argv[ii] || tmpval < 1) {
+          fprintf(stderr,"Invalid port '%s' given for rtnet port.\n",argv[ii]);
+          usage();
+          return 1;
+        }
+        port = tmpval;
+        rtnetPortSet=true;
+        break;
+      case RtnetHost:
+        host = argv[ii];
+        break;
+      }
+      prevArgSet=false;
+    } else {
+      if (!strcmp(argv[ii],"-p")) {
+        prevArgSet=true;
+        prevArg=RtnetPort;
+      } else if (!strcmp(argv[ii],"-H")) {
+        prevArgSet=true;
+        prevArg=RtnetHost;
+      } else if (!strcmp(argv[ii],"-h")) {
+        usage();
+        return 0;
+      } else {
+        fprintf(stderr,"Unknown argument %s\n",argv[ii]);
+        usage();
+        return 1;
+      }
+    }
+  }
+  if (!rtnetPortSet) {
+    fprintf(stderr,"RTNet port must be set.\n");
+    usage();
+    return 1;
+  }
+  boost::shared_ptr<TimerManager> timeMgr(new TimerManager);
+  boost::shared_ptr<ThreadFactory> thFactory(new PlatformThreadFactory);
+  timeMgr->threadFactory(thFactory);
+  timeMgr->start();
+  boost::shared_ptr<RtnetDataHandler> dataHandler(new RtnetDataHandler());
+  boost::shared_ptr<Client> clnt(new Client(host,port,timeMgr,dataHandler));
+
+  while (!STOP)
+    usleep(100);
+
+  // application cleanup
+  timeMgr->stop();
+  clnt->stop();
+  printf("Clean stop\n");
+  return 0;
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/rtnet_sdo_example_dump.cpp
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/rtnet_sdo_example_dump.cpp	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/rtnet_sdo_example_dump.cpp	(revision 4941)
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <cstdlib>
+#include <iostream>
+
+#include <transport/TBufferTransports.h>
+#include <transport/TFDTransport.h>
+#include <transport/TZlibTransport.h>
+#include <protocol/TBinaryProtocol.h>
+#include <protocol/TDebugProtocol.h>
+#include <protocol/TProtocolTap.h>
+
+using namespace std;
+using boost::shared_ptr;
+using namespace apache::thrift::transport;
+using namespace apache::thrift::protocol;
+
+void usage() {
+  fprintf(stderr,
+      "usage: thrift_dump {-b|-f|-s} < input > ouput\n"
+      "  -b TBufferedTransport messages\n"
+      "  -f TFramedTransport messages\n"
+      "  -z TZlibTransport messages\n"
+      "  -s Raw structures\n");
+  exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[]) {
+  if (argc != 2) {
+    usage();
+  }
+
+  shared_ptr<TTransport> stdin_trans(new TFDTransport(STDIN_FILENO));
+  shared_ptr<TTransport> itrans;
+
+  if (argv[1] == std::string("-b") || argv[1] == std::string("-s")) {
+    itrans.reset(new TBufferedTransport(stdin_trans));
+  } else if (argv[1] == std::string("-z")) {
+    itrans.reset(new TZlibTransport(stdin_trans));
+  } else if (argv[1] == std::string("-f")) {
+    itrans.reset(new TFramedTransport(stdin_trans));
+  } else {
+    usage();
+  }
+
+  shared_ptr<TProtocol> iprot(new TBinaryProtocol(itrans));
+  shared_ptr<TProtocol> oprot(
+      new TDebugProtocol(
+        shared_ptr<TTransport>(new TBufferedTransport(
+          shared_ptr<TTransport>(new TFDTransport(STDOUT_FILENO))))));
+
+  TProtocolTap tap(iprot, oprot);
+
+  try {
+    if (argv[1] == std::string("-s")) {
+      for (;;) {
+        tap.skip(T_STRUCT);
+      }
+    } else {
+      std::string name;
+      TMessageType messageType;
+      int32_t seqid;
+      for (;;) {
+        tap.readMessageBegin(name, messageType, seqid);
+        tap.skip(T_STRUCT);
+        tap.readMessageEnd();
+      }
+    }
+  } catch (TProtocolException exn) {
+    cout << "Protocol Exception: " << exn.what() << endl;
+  } catch (...) {
+    oprot->getTransport()->flush();
+  }
+
+  cout << endl;
+
+  return 0;
+}
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet.thrift
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet.thrift	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet.thrift	(revision 4941)
@@ -0,0 +1,22 @@
+include "rtnet_data.thrift"
+
+namespace cpp com.gpssolutions.rtnet
+namespace java com.gpssolutions.rtnet
+namespace perl gpss
+
+service RtnetData {
+  // used for plots
+  oneway void startDataStream(),
+  oneway void registerRtnet(1: rtnet_data.RtnetInformation info),
+  oneway void handleZDAmb(1: list<rtnet_data.ZDAmb> ambList),
+  oneway void handleDDAmbresBaselines(1: list<rtnet_data.DDAmbresBaseline> ambList),
+  oneway void handleSatelliteXYZ(1: list<rtnet_data.SatelliteXYZ> svXYZList),
+  oneway void handleStationInfo(1: list<rtnet_data.StationInfo> stationList),
+  oneway void handleStationAuxInfo(1: list<rtnet_data.StationAuxInfo> stationAuxList),
+
+  // used for everything else
+  oneway void handleDGPSCorr(1: list<rtnet_data.DGPSCorr> dgpsList),
+  oneway void handleSatelliteClock(1: list<rtnet_data.SatelliteClock> svList),
+  oneway void handleEpochResults(1: rtnet_data.RtnetEpoch epoch)
+}
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet_data.thrift
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet_data.thrift	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet_data.thrift	(revision 4941)
@@ -0,0 +1,385 @@
+namespace cpp com.gpssolutions.rtnet
+namespace java com.gpssolutions.rtnet
+namespace perl gpss
+
+struct PosNEU {
+  1: double n, // north (meters)
+  2: double e, // east (meters)
+  3: double u  // up (meters)
+}
+
+struct PosXYZ {
+  1: double x, // x (meters)
+  2: double y, // y (meters)
+  3: double z  // z (meters)
+}
+
+struct StationInfo {
+  1: string ID,
+  2: PosNEU sigma0,
+  3: PosNEU sigmaNoise,
+  4: PosXYZ xyz,
+}
+
+struct StationAuxInfo {
+  1: string ID,
+  2: string receiverID,
+  3: string antennaID,
+  4: PosNEU eccentricity,
+}
+
+enum ConstellationType {
+  GPS     = 1,
+  GLONASS = 2,
+  SBAS    = 3,
+  GALILEO = 4,
+  QZSS    = 5,
+  COMPASS = 6,
+}
+
+// consider adding health flags
+struct SatelliteXYZ {
+  1: byte ID,
+  2: ConstellationType constellation,
+  3: PosXYZ xyz,
+//  4: double lon,
+//  5: double lat
+}
+
+enum FrequencyType {
+  // GPS phase
+  Gp1=1,
+  Gp2=2,
+  Gp5=3,
+  GpIF=4,
+  GpGF=5,
+  GpWL=6,
+  GpMW=7,
+
+  // Galileo phase
+  Ep1=8,
+  Ep5=9,
+  Ep6=10,
+  Ep7=11,
+  Ep8=12,
+  EpIF=13,
+  EpGF=14,
+  EpWL=15,
+  EpMW=16,
+
+  // GLONASS phase
+  Rp1=17,
+  Rp2=18,
+  RpIF=19,
+  RpGF=20,
+  RpWL=21,
+  RpMW=22,
+
+  // GPS code
+  Gc1=23,
+  Gc2=24,
+  Gc5=25,
+  GcIF=26,
+  GcGF=27,
+
+  // Galileo code
+  Ec1=28,
+  Ec5=29,
+  Ec6=30,
+  Ec7=31,
+  Ec8=32,
+  EcIF=33,
+  EcGF=34,
+
+  // GLONASS code
+  Rc1=35,
+  Rc2=36,
+  RcIF=37,
+  RcGF=38,
+
+  // GPS doppler
+  Gd1=39,
+  Gd2=40,
+}
+
+struct ZDAmb {
+  1: byte satelliteID,
+  2: ConstellationType constellation,
+  3: string stationID,
+  4: FrequencyType frequency,
+  5: bool constrainedFlag,
+  6: i16 duration,
+  7: bool hasObsFlag,
+ 10: bool isNewAmb,
+ 11: bool isResetAmbL1p,
+ 12: bool isResetAmbClock,
+  8: optional double azimuth,
+  9: optional double elevation,
+}
+
+enum AmbresStatus
+{
+  AmbFloat = 1,
+  AmbFixed = 2,
+  AmbDumped = 3
+}
+
+struct DDAmbres
+{
+  1: byte satelliteID,
+  2: ConstellationType constellation,
+  3: AmbresStatus statusFlag,
+  4: bool hasObsFlag,
+}
+
+struct DDAmbresBaseline
+{
+  1: string stationID_1,
+  2: string stationID_2,
+  3: bool redundant,
+  4: optional list<DDAmbres> wideLaneStatisticList,
+  5: optional list<DDAmbres> narrowLaneStatisticList,
+  6: optional list<DDAmbres> l1StatisticList,
+  7: optional list<DDAmbres> l2StatisticList,
+}
+
+/*struct DDAmbresStatistic {
+  1: list<DDAmbresBaseline> baselineList
+}*/
+
+/**
+ * Stores information about rtnet job.
+ * For now, it only stores the rtnet job's name (should be unique).
+ * Eventually, may store other useful information such as the
+ * input file contents, the name of who started the job, etc.
+ */
+struct RtnetInformation {
+  1: string jobName
+}
+
+// Data needed for plots
+
+struct SatelliteClock {
+  1: byte satelliteID,
+  2: ConstellationType constellation,
+  3: double clock,    // satellite clock estimate (s)
+  4: double clock_err, // satellite clock error (s)
+}
+
+struct DGPSCorr {
+  1: byte satelliteID,
+  2: ConstellationType constellation,
+  3: double a0,      // non-dispersive correction (ie, clock)
+  4: double a0e,     // formal error for a0
+  5: double aN,      // non-dispersive correction, N-S gradient
+  6: double aE,      // non-dispersive correction, E-W gradient
+  7: double i0,      // dispersive correction
+  8: double iN,      // dispersive correction, N-S gradient
+  9: double iE,      // dispersive correction, E-W gradient
+ 10: i16 nsdfix,     // number of stations with fixed ZD ambiguity
+ 11: i16 nsta,       // number of stations
+ 12: i16 cjumpCnt,   // correction jump counter
+ 13: double deltaMW, // MW bias
+ 14: double deltaP3, // P3 bias
+ 15: double te0,     // vertical TEC
+ 16: double teN,     // vertical TEC, N-S gradient
+ 17: double teE,     // vertical TEC, E-W gradient
+ 18: double teNN,    // vertical TEC, gradient, 2nd order
+ 19: double teEE,    // vertical TEC, gradient, 2nd order
+ 20: double teNE,    // vertical TEC, gradient, 2nd order
+ 21: optional double d0, // P4 system (not used)
+ 22: optional double dN, // P4 system (not used)
+ 23: optional double dE, // P4 system (not used)
+}
+
+enum SolutionQuality {
+  NoData=0,       // No data for receiver for the epoch. In network mode, may also mean
+                  // unable to create a baseline to a fixed station.
+  LowNsv=1,       // Not enough SVs or solution has very high formal error
+  NoCorrection=2, // Have a solution but no correction values (legacy from P4)
+  HighRMS=3,      // Have a solution with correction values, but the RMS is high
+  LowRMS=4,       // Have a solution with correction values with a good RMS
+}
+
+struct StationPosition {
+   1: double x,    // x position (m) (a-priori + estimate)
+   2: double xe,   // x error (m)
+   3: double y,    // y position (m) (a-priori + estimate)
+   4: double ye,   // y error (m)
+   5: double z,    // z position (m) (a-priori + estimate)
+   6: double ze,   // z error (m)
+   7: double eh,   // ellipsoid height (m)
+   8: double ehe,  // ellipsoid height error (m)
+   9: double dn,   // north position (m)
+  10: double dne,  // north position error (m)
+  11: double de,   // east position (m)
+  12: double dee,  // east position error (m)
+  13: double dh,   // height position (m)
+  14: double dhe,  // height position error (m)
+  15: double GDOP, // (m)
+  16: double PDOP, // (m)
+  17: byte  nsv_gps_used, // number of GPS satellites used in position calculation
+  18: byte  nsv_glonass_used, // number of GLONASS satellites used in position calculation
+  19: SolutionQuality qFlag, // flag used to estimate quality of solution
+}
+
+struct SatelliteEleAzi {
+  1: byte ID, // satellite PRN/slot number
+  2: ConstellationType constellation,
+  3: double elevation, // elevation in degrees
+  4: double azimuth    // azimuth in degrees
+}
+
+enum LinearCombination {
+  L1   =  1,
+  L2   =  2,
+  L3   =  3,
+  L1L2 =  4,
+  IF   =  5,
+  GF   =  6,
+  MW   =  7,
+  MWIF =  8,
+  PL   =  9, // (P1+L1)/2 (ionospheric-free)
+  WL   = 10,
+}
+
+enum ProcessedLC {
+  Gp1, Gp2, Gp5,           GpIF, GpGF, GpWL, GpMW, // GPS Phase
+  Ep1, Ep5, Ep6, Ep7, Ep8, EpIF, EpGF, EpWL, EpMW, // Galileo Phase
+  Rp1, Rp2,                RpIF, RpGF, RpWL, RpMW, // Glonass Phase
+  Gc1, Gc2, Gc5,           GcIF, GcGF,             // GPS Code
+  Ec1, Ec5, Ec6, Ec7, Ec8, EcIF, EcGF,             // Galileo Code
+  Rc1, Rc2,                RcIF, RcGF,             // Glonass Code
+  Gd1, Gd2,                                        // GPS Doppler
+  GpPL,                                            // GPS (P1+L1)/2
+  RpPL,                                            // GLONASS (P1+L1)/2
+  invalidLC
+}
+
+struct ObservationMarkCount {
+  1: byte n_mark_none, //  0 (not marked)
+  2: byte n_mark_mis,  //  1 (missing marked -- if processing dual-frequency data, marked if one frequency is missing)
+  3: byte n_mark_ele,  //  2 (elevation marked)
+  4: byte n_mark_cor,  //  3 (DGPS correction marked)
+  5: byte n_mark_orb,  //  4 (orbit marked)
+  6: byte n_mark_unp,  //  5 (unpaired observable between LC1 and LC2)
+  7: byte n_mark_ca,   //  6 (CA marked)
+  8: byte n_mark_out,  //  7 (outlier)
+  9: byte n_mark_crx,  //  8 (SATCRUX marked)
+ 10: byte n_mark_iod,  //  9 (not used by current version of rtnet)
+ 11: byte n_mark_dcb,  // 10 (satellite DCB marked)
+ 12: byte n_mark_few,  // 11 (not used by current version of rtnet)
+ 13: byte n_mark_blu,  // 12 (blunder marked -- something to do with outlier detection. Perhaps if set, internal logic error in rtnet?)
+ 14: byte n_mark_ban,  // 13 (not enough satellites for Bancroft solution)
+ 15: byte n_mark_l1m,  // 14 (L1 missing)
+ 16: byte n_mark_l1i,  // 15 (not used by current version of rtnet)
+ 17: byte n_mark_ion,  // 16 (ionospheric delay marked)
+ 18: byte n_mark_trp,  // 17 (troposphere marked)
+ 19: byte n_mark_glo,  // 18 (GLONASS phase marked because channel number is unknown)
+ 20: byte n_mark_exc,  // 19 (satellite excluded from processing by user or because satellite is unhealthy)
+ 21: byte n_mark_hlt,  // 20 (not used by current version of rtnet)
+ 22: byte n_mark_old,  // 21 (marked because orbit is too old)
+ 23: byte n_mark_rho,  // 22 (computing range to satellite failed--solution did not converge)
+ 24: byte n_mark_oth,  // 23 (other marked)
+}
+
+struct SvResidualInfo {
+  1: byte ID, // satellite PRN/slot number
+  2: ConstellationType constellation,
+  3: double residual, // meters
+}
+
+struct ResidualInfo {
+  1: ProcessedLC lc,
+  2: double meanResid,
+  3: double pv,
+  4: list<SvResidualInfo> svResid,
+}
+
+struct StationResults {
+  1: string stationName,
+  2: LinearCombination lc, // linear combination of solution
+  // number of observations
+  3: byte n_p1, // # of P1 observations
+  4: byte n_l1, // # of L1 observations
+  5: byte n_p2, // # of P2 observations
+  6: byte n_l2, // # of L2 observations
+  7: byte n_g1, // # of G1 observations (GLONASS P1)
+  8: byte n_g2, // # of G2 observations (GLONASS P2)
+  9: list<SatelliteEleAzi> svPosList, // list of satellites used in calculation
+ 10: double rcv_clk,  // receiver clock (m)
+ 11: double rcv_clke, // receiver clock error (m)
+ 12: double GDOP,     // GDOP obtained with satellites used in processing
+ 13: double PDOP,     // PDOP obtained with satellites used in processing
+ // number of observations for each mark (including mark_none, ie, not marked)
+ 14: ObservationMarkCount n_mark_p1,
+ 15: ObservationMarkCount n_mark_l1,
+ 16: ObservationMarkCount n_mark_p2,
+ 17: ObservationMarkCount n_mark_l2,
+ 18: ObservationMarkCount n_mark_l3,
+ // station position and estimates
+ 19: optional StationPosition filtered_result,    // primary position solution (optional because station could be fixed)
+ 20: optional StationPosition se_result, // single epoch result
+ // troposphere data
+ 21: optional double ztd,  // zenith delay (m)
+ 22: optional double ztde, // zenith delay error (m)
+ 23: list<ResidualInfo> residList, // residual information for each LC
+}
+// satellite elevation and azimuth (list)
+
+enum MissingEpochData
+{
+  NoError                       = 0, // solution was generated
+  MissingAllStationObservation  = 1, // no station observations available
+  MissingOrbit                  = 2, // no orbit information available
+  MissingCorrection             = 3, // correction is unavailable
+  KalmanFilterFailed            = 4, // Kalman filter step failed
+}
+
+enum MissingStationData
+{
+  NoError                    = 0, // station could be processed
+  StationFixed               = 1, // no position result because station is fixed
+  MissingStationObservation  = 2, // no observations available for station
+  TooFewBancroft             = 3, // not enough satellites to generate Bancroft solution
+  MissingStationInfo         = 4, // station missing from coordinate file
+  MissingAntennaInfo         = 5, // station's antenna not present in ATX file
+                                  // (if this is an immediate error by rtnet, this flag isn't needed)
+  StationUserMarked          = 6, // station was removed from processing by user
+}
+
+struct RtnetEpoch {
+  1: i16 mjlDay,  // MJL day of epoch
+  2: i32 msecDay, // time of day (msec)
+  3: list<StationResults> stationResultList, // set for each linear combination
+  4: MissingEpochData missing, // set to NoError if data is present,
+                               // otherwise solution could not be generated because of specified reason
+  5: map<string,MissingStationData> dataAvailableList, // flag for each station in STALIST
+  6: i32 processTime, // process time (dt), msec
+  7: i32 compTime,    // computation time (dt_proc), msec
+  8: i32 latency,     // latency, msec
+}
+
+// Needed for plots
+//Per station data:
+//X Troposphere: quality flag, ztda, ztd, ztde
+//X Number of observations per station (ie, # P1, # L1, # L2, # G1, etc)
+//X GDOP, PDOP, # sv_used
+//X mres, pv, res_code_flag
+//X x, xi, xe, y, yi, ye, z, zi, ze, dn, dne, de, dee, dh, dhe
+//X receiver clk, clki, clke
+//List of satellites used
+//# new ambiguities, # clock resets, # L1 ambiguity resets
+
+//# of each mark flag for P1, L1 and L2
+//-- so perhaps 10 mark 0s for P1, 2 mark 3s for P1, 10 mark 0s for L1, etc.
+
+// other ideas:
+// Send basic input file information or entire input file.
+// Send current file used for orbits (or host/port if using external orbits).
+
+
+//----
+//Data latency per epoch. Processing time per step.
+//slant delay (maybe same as mres) (per station, per satellite, per LC, per epoch)
+
Index: /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet_js.thrift
===================================================================
--- /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet_js.thrift	(revision 4941)
+++ /trunk/GnssCenter/thrift/rtnet_sdo_example/thrift_template/rtnet_js.thrift	(revision 4941)
@@ -0,0 +1,26 @@
+include "rtnet_data.thrift"
+
+namespace cpp com.gpssolutions.rtnet_js
+namespace java com.gpssolutions.rtnet_js
+
+struct UpdateStatus {
+  1: byte stationInfoUpdated,
+  2: byte stationAuxInfoUpdated,
+  3: byte rtnetInfoUpdated,
+  4: i32  lastEpoch
+}
+
+exception InvalidArgument {
+  1: string why
+}
+
+service RtnetDataJs {
+  list<rtnet_data.RtnetInformation> getJobList(),
+  list<rtnet_data.ZDAmb> lastZDAmb(1: string jobName) throws (1:InvalidArgument err),
+  list<rtnet_data.DDAmbresBaseline> lastDDAmbresBaselines(1: string jobName) throws (1:InvalidArgument err),
+  list<rtnet_data.SatelliteXYZ> getSatelliteXYZ(1: string jobName) throws (1:InvalidArgument err),
+  list<rtnet_data.StationInfo> getStationInfo(1: string jobName) throws (1:InvalidArgument err),
+  list<rtnet_data.StationAuxInfo> getStationAuxInfo(1: string jobName) throws (1:InvalidArgument err),
+  UpdateStatus getUpdateStatus(1: string jobName) throws (1:InvalidArgument err)
+}
+
