<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "content/browser/device_sensors/data_fetcher_shared_memory.h"
#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_javascript_dialog_manager.h"

namespace content {

namespace {

class FakeDataFetcher : public DataFetcherSharedMemory {
 public:
  FakeDataFetcher()
      : started_orientation_(false, false),
        stopped_orientation_(false, false),
        started_motion_(false, false),
        stopped_motion_(false, false),
        started_light_(false, false),
        stopped_light_(false, false),
        sensor_data_available_(true) {}
  virtual ~FakeDataFetcher() { }

  virtual bool Start(ConsumerType consumer_type, void* buffer) override {
    EXPECT_TRUE(buffer);

    switch (consumer_type) {
      case CONSUMER_TYPE_MOTION:
        {
          DeviceMotionHardwareBuffer* motion_buffer =
              static_cast<DeviceMotionHardwareBuffer*>(buffer);
          if (sensor_data_available_)
            UpdateMotion(motion_buffer);
          SetMotionBufferReady(motion_buffer);
          started_motion_.Signal();
        }
        break;
      case CONSUMER_TYPE_ORIENTATION:
        {
          DeviceOrientationHardwareBuffer* orientation_buffer =
              static_cast<DeviceOrientationHardwareBuffer*>(buffer);
          if (sensor_data_available_)
            UpdateOrientation(orientation_buffer);
          SetOrientationBufferReady(orientation_buffer);
          started_orientation_.Signal();
        }
        break;
      case CONSUMER_TYPE_LIGHT:
        {
          DeviceLightHardwareBuffer* light_buffer =
              static_cast<DeviceLightHardwareBuffer*>(buffer);
          UpdateLight(light_buffer,
                      sensor_data_available_
                          ? 100
                          : std::numeric_limits<double>::infinity());
          started_light_.Signal();
        }
        break;
      default:
        return false;
    }
    return true;
  }

  virtual bool Stop(ConsumerType consumer_type) override {
    switch (consumer_type) {
      case CONSUMER_TYPE_MOTION:
        stopped_motion_.Signal();
        break;
      case CONSUMER_TYPE_ORIENTATION:
        stopped_orientation_.Signal();
        break;
      case CONSUMER_TYPE_LIGHT:
        stopped_light_.Signal();
        break;
      default:
        return false;
    }
    return true;
  }

  virtual void Fetch(unsigned consumer_bitmask) override {
    FAIL() << "fetch should not be called";
  }

  virtual FetcherType GetType() const override {
    return FETCHER_TYPE_DEFAULT;
  }

  void SetSensorDataAvailable(bool available) {
    sensor_data_available_ = available;
  }

  void SetMotionBufferReady(DeviceMotionHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void SetOrientationBufferReady(DeviceOrientationHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void UpdateMotion(DeviceMotionHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.accelerationX = 1;
    buffer->data.hasAccelerationX = true;
    buffer->data.accelerationY = 2;
    buffer->data.hasAccelerationY = true;
    buffer->data.accelerationZ = 3;
    buffer->data.hasAccelerationZ = true;

    buffer->data.accelerationIncludingGravityX = 4;
    buffer->data.hasAccelerationIncludingGravityX = true;
    buffer->data.accelerationIncludingGravityY = 5;
    buffer->data.hasAccelerationIncludingGravityY = true;
    buffer->data.accelerationIncludingGravityZ = 6;
    buffer->data.hasAccelerationIncludingGravityZ = true;

    buffer->data.rotationRateAlpha = 7;
    buffer->data.hasRotationRateAlpha = true;
    buffer->data.rotationRateBeta = 8;
    buffer->data.hasRotationRateBeta = true;
    buffer->data.rotationRateGamma = 9;
    buffer->data.hasRotationRateGamma = true;

    buffer->data.interval = 100;
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void UpdateOrientation(DeviceOrientationHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.alpha = 1;
    buffer->data.hasAlpha = true;
    buffer->data.beta = 2;
    buffer->data.hasBeta = true;
    buffer->data.gamma = 3;
    buffer->data.hasGamma = true;
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void UpdateLight(DeviceLightHardwareBuffer* buffer, double lux) {
    buffer->seqlock.WriteBegin();
    buffer->data.value = lux;
    buffer->seqlock.WriteEnd();
  }

  base::WaitableEvent started_orientation_;
  base::WaitableEvent stopped_orientation_;
  base::WaitableEvent started_motion_;
  base::WaitableEvent stopped_motion_;
  base::WaitableEvent started_light_;
  base::WaitableEvent stopped_light_;
  bool sensor_data_available_;

 private:
  DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher);
};

class DeviceInertialSensorBrowserTest : public ContentBrowserTest  {
 public:
  DeviceInertialSensorBrowserTest()
      : fetcher_(NULL),
        io_loop_finished_event_(false, false) {
  }

  virtual void SetUpOnMainThread() override {
    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&DeviceInertialSensorBrowserTest::SetUpOnIOThread, this));
    io_loop_finished_event_.Wait();
  }

  void SetUpOnIOThread() {
    fetcher_ = new FakeDataFetcher();
    DeviceInertialSensorService::GetInstance()->
        SetDataFetcherForTesting(fetcher_);
    io_loop_finished_event_.Signal();
  }

  void DelayAndQuit(base::TimeDelta delay) {
    base::PlatformThread::Sleep(delay);
    base::MessageLoop::current()->QuitWhenIdle();
  }

  void WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta delay) {
    ShellJavaScriptDialogManager* dialog_manager=
        static_cast<ShellJavaScriptDialogManager*>(
            shell()->GetJavaScriptDialogManager());

    scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
    dialog_manager->set_dialog_request_callback(
        base::Bind(&DeviceInertialSensorBrowserTest::DelayAndQuit, this,
            delay));
    runner->Run();
  }

  FakeDataFetcher* fetcher_;

 private:
  base::WaitableEvent io_loop_finished_event_;
};

IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationTest) {
  // The test page will register an event handler for orientation events,
  // expects to get an event with fake values, then removes the event
  // handler and navigates to #pass.
  GURL test_url = GetTestUrl("device_sensors", "device_orientation_test.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);

  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
  fetcher_->started_orientation_.Wait();
  fetcher_->stopped_orientation_.Wait();
}

IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, LightTest) {
  // The test page will register an event handler for light events,
  // expects to get an event with fake values, then removes the event
  // handler and navigates to #pass.
  GURL test_url = GetTestUrl("device_sensors", "device_light_test.html");

  // TODO(riju): remove command line args when the feature goes stable.
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableExperimentalWebPlatformFeatures)) {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableExperimentalWebPlatformFeatures);
  }

  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);

  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
  fetcher_->started_light_.Wait();
  fetcher_->stopped_light_.Wait();
}

IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionTest) {
  // The test page will register an event handler for motion events,
  // expects to get an event with fake values, then removes the event
  // handler and navigates to #pass.
  GURL test_url = GetTestUrl("device_sensors", "device_motion_test.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);

  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
  fetcher_->started_motion_.Wait();
  fetcher_->stopped_motion_.Wait();
}

// crbug/416406. The test is flaky.
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
                       DISABLED_LightOneOffInfintyTest) {
  // The test page will register an event handler for light events,
  // expects to get an event with value equal to Infinity. This tests that the
  // one-off infinity event still propagates to window after the alert is
  // dismissed and the callback is invoked which navigates to #pass.
  fetcher_->SetSensorDataAvailable(false);

  // TODO(riju): remove command line args when the feature goes stable.
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableExperimentalWebPlatformFeatures)) {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableExperimentalWebPlatformFeatures);
  }

  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);

  GURL test_url =
      GetTestUrl("device_sensors", "device_light_infinity_test.html");
  shell()->LoadURL(test_url);

  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));

  fetcher_->started_light_.Wait();
  fetcher_->stopped_light_.Wait();
  same_tab_observer.Wait();
  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}

// Flaking in the android try bot. See http://crbug.com/360578.
#if defined(OS_ANDROID)
#define MAYBE_OrientationNullTestWithAlert DISABLED_OrientationNullTestWithAlert
#else
#define MAYBE_OrientationNullTestWithAlert OrientationNullTestWithAlert
#endif
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
    MAYBE_OrientationNullTestWithAlert) {
  // The test page will register an event handler for orientation events,
  // expects to get an event with null values. The test raises a modal alert
  // dialog with a delay to test that the one-off null-event still propagates
  // to window after the alert is dismissed and the callback is invoked which
  // navigates to #pass.
  fetcher_->SetSensorDataAvailable(false);
  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);

  GURL test_url = GetTestUrl("device_sensors",
                             "device_orientation_null_test_with_alert.html");
  shell()->LoadURL(test_url);

  // TODO(timvolodine): investigate if it is possible to test this without
  // delay, crbug.com/360044.
  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));

  fetcher_->started_orientation_.Wait();
  fetcher_->stopped_orientation_.Wait();
  same_tab_observer.Wait();
  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}

// Flaking in the android try bot. See http://crbug.com/360578.
#if defined(OS_ANDROID)
#define MAYBE_MotionNullTestWithAlert DISABLED_MotionNullTestWithAlert
#else
#define MAYBE_MotionNullTestWithAlert MotionNullTestWithAlert
#endif
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
    MAYBE_MotionNullTestWithAlert) {
  // The test page will register an event handler for motion events,
  // expects to get an event with null values. The test raises a modal alert
  // dialog with a delay to test that the one-off null-event still propagates
  // to window after the alert is dismissed and the callback is invoked which
  // navigates to #pass.
  fetcher_->SetSensorDataAvailable(false);
  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);

  GURL test_url =
      GetTestUrl("device_sensors", "device_motion_null_test_with_alert.html");
  shell()->LoadURL(test_url);

  // TODO(timvolodine): investigate if it is possible to test this without
  // delay, crbug.com/360044.
  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));

  fetcher_->started_motion_.Wait();
  fetcher_->stopped_motion_.Wait();
  same_tab_observer.Wait();
  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}

}  //  namespace

}  //  namespace content
<commit_msg>Disable DeviceInertialSensorBrowserTest.MotionNullTestWithAlert on windows<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "content/browser/device_sensors/data_fetcher_shared_memory.h"
#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_javascript_dialog_manager.h"

namespace content {

namespace {

class FakeDataFetcher : public DataFetcherSharedMemory {
 public:
  FakeDataFetcher()
      : started_orientation_(false, false),
        stopped_orientation_(false, false),
        started_motion_(false, false),
        stopped_motion_(false, false),
        started_light_(false, false),
        stopped_light_(false, false),
        sensor_data_available_(true) {}
  virtual ~FakeDataFetcher() { }

  virtual bool Start(ConsumerType consumer_type, void* buffer) override {
    EXPECT_TRUE(buffer);

    switch (consumer_type) {
      case CONSUMER_TYPE_MOTION:
        {
          DeviceMotionHardwareBuffer* motion_buffer =
              static_cast<DeviceMotionHardwareBuffer*>(buffer);
          if (sensor_data_available_)
            UpdateMotion(motion_buffer);
          SetMotionBufferReady(motion_buffer);
          started_motion_.Signal();
        }
        break;
      case CONSUMER_TYPE_ORIENTATION:
        {
          DeviceOrientationHardwareBuffer* orientation_buffer =
              static_cast<DeviceOrientationHardwareBuffer*>(buffer);
          if (sensor_data_available_)
            UpdateOrientation(orientation_buffer);
          SetOrientationBufferReady(orientation_buffer);
          started_orientation_.Signal();
        }
        break;
      case CONSUMER_TYPE_LIGHT:
        {
          DeviceLightHardwareBuffer* light_buffer =
              static_cast<DeviceLightHardwareBuffer*>(buffer);
          UpdateLight(light_buffer,
                      sensor_data_available_
                          ? 100
                          : std::numeric_limits<double>::infinity());
          started_light_.Signal();
        }
        break;
      default:
        return false;
    }
    return true;
  }

  virtual bool Stop(ConsumerType consumer_type) override {
    switch (consumer_type) {
      case CONSUMER_TYPE_MOTION:
        stopped_motion_.Signal();
        break;
      case CONSUMER_TYPE_ORIENTATION:
        stopped_orientation_.Signal();
        break;
      case CONSUMER_TYPE_LIGHT:
        stopped_light_.Signal();
        break;
      default:
        return false;
    }
    return true;
  }

  virtual void Fetch(unsigned consumer_bitmask) override {
    FAIL() << "fetch should not be called";
  }

  virtual FetcherType GetType() const override {
    return FETCHER_TYPE_DEFAULT;
  }

  void SetSensorDataAvailable(bool available) {
    sensor_data_available_ = available;
  }

  void SetMotionBufferReady(DeviceMotionHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void SetOrientationBufferReady(DeviceOrientationHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void UpdateMotion(DeviceMotionHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.accelerationX = 1;
    buffer->data.hasAccelerationX = true;
    buffer->data.accelerationY = 2;
    buffer->data.hasAccelerationY = true;
    buffer->data.accelerationZ = 3;
    buffer->data.hasAccelerationZ = true;

    buffer->data.accelerationIncludingGravityX = 4;
    buffer->data.hasAccelerationIncludingGravityX = true;
    buffer->data.accelerationIncludingGravityY = 5;
    buffer->data.hasAccelerationIncludingGravityY = true;
    buffer->data.accelerationIncludingGravityZ = 6;
    buffer->data.hasAccelerationIncludingGravityZ = true;

    buffer->data.rotationRateAlpha = 7;
    buffer->data.hasRotationRateAlpha = true;
    buffer->data.rotationRateBeta = 8;
    buffer->data.hasRotationRateBeta = true;
    buffer->data.rotationRateGamma = 9;
    buffer->data.hasRotationRateGamma = true;

    buffer->data.interval = 100;
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void UpdateOrientation(DeviceOrientationHardwareBuffer* buffer) {
    buffer->seqlock.WriteBegin();
    buffer->data.alpha = 1;
    buffer->data.hasAlpha = true;
    buffer->data.beta = 2;
    buffer->data.hasBeta = true;
    buffer->data.gamma = 3;
    buffer->data.hasGamma = true;
    buffer->data.allAvailableSensorsAreActive = true;
    buffer->seqlock.WriteEnd();
  }

  void UpdateLight(DeviceLightHardwareBuffer* buffer, double lux) {
    buffer->seqlock.WriteBegin();
    buffer->data.value = lux;
    buffer->seqlock.WriteEnd();
  }

  base::WaitableEvent started_orientation_;
  base::WaitableEvent stopped_orientation_;
  base::WaitableEvent started_motion_;
  base::WaitableEvent stopped_motion_;
  base::WaitableEvent started_light_;
  base::WaitableEvent stopped_light_;
  bool sensor_data_available_;

 private:
  DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher);
};

class DeviceInertialSensorBrowserTest : public ContentBrowserTest  {
 public:
  DeviceInertialSensorBrowserTest()
      : fetcher_(NULL),
        io_loop_finished_event_(false, false) {
  }

  virtual void SetUpOnMainThread() override {
    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&DeviceInertialSensorBrowserTest::SetUpOnIOThread, this));
    io_loop_finished_event_.Wait();
  }

  void SetUpOnIOThread() {
    fetcher_ = new FakeDataFetcher();
    DeviceInertialSensorService::GetInstance()->
        SetDataFetcherForTesting(fetcher_);
    io_loop_finished_event_.Signal();
  }

  void DelayAndQuit(base::TimeDelta delay) {
    base::PlatformThread::Sleep(delay);
    base::MessageLoop::current()->QuitWhenIdle();
  }

  void WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta delay) {
    ShellJavaScriptDialogManager* dialog_manager=
        static_cast<ShellJavaScriptDialogManager*>(
            shell()->GetJavaScriptDialogManager());

    scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
    dialog_manager->set_dialog_request_callback(
        base::Bind(&DeviceInertialSensorBrowserTest::DelayAndQuit, this,
            delay));
    runner->Run();
  }

  FakeDataFetcher* fetcher_;

 private:
  base::WaitableEvent io_loop_finished_event_;
};

IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationTest) {
  // The test page will register an event handler for orientation events,
  // expects to get an event with fake values, then removes the event
  // handler and navigates to #pass.
  GURL test_url = GetTestUrl("device_sensors", "device_orientation_test.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);

  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
  fetcher_->started_orientation_.Wait();
  fetcher_->stopped_orientation_.Wait();
}

IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, LightTest) {
  // The test page will register an event handler for light events,
  // expects to get an event with fake values, then removes the event
  // handler and navigates to #pass.
  GURL test_url = GetTestUrl("device_sensors", "device_light_test.html");

  // TODO(riju): remove command line args when the feature goes stable.
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableExperimentalWebPlatformFeatures)) {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableExperimentalWebPlatformFeatures);
  }

  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);

  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
  fetcher_->started_light_.Wait();
  fetcher_->stopped_light_.Wait();
}

IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionTest) {
  // The test page will register an event handler for motion events,
  // expects to get an event with fake values, then removes the event
  // handler and navigates to #pass.
  GURL test_url = GetTestUrl("device_sensors", "device_motion_test.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);

  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
  fetcher_->started_motion_.Wait();
  fetcher_->stopped_motion_.Wait();
}

// crbug/416406. The test is flaky.
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
                       DISABLED_LightOneOffInfintyTest) {
  // The test page will register an event handler for light events,
  // expects to get an event with value equal to Infinity. This tests that the
  // one-off infinity event still propagates to window after the alert is
  // dismissed and the callback is invoked which navigates to #pass.
  fetcher_->SetSensorDataAvailable(false);

  // TODO(riju): remove command line args when the feature goes stable.
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableExperimentalWebPlatformFeatures)) {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableExperimentalWebPlatformFeatures);
  }

  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);

  GURL test_url =
      GetTestUrl("device_sensors", "device_light_infinity_test.html");
  shell()->LoadURL(test_url);

  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));

  fetcher_->started_light_.Wait();
  fetcher_->stopped_light_.Wait();
  same_tab_observer.Wait();
  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}

// Flaking in the android try bot. See http://crbug.com/360578.
#if defined(OS_ANDROID)
#define MAYBE_OrientationNullTestWithAlert DISABLED_OrientationNullTestWithAlert
#else
#define MAYBE_OrientationNullTestWithAlert OrientationNullTestWithAlert
#endif
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
    MAYBE_OrientationNullTestWithAlert) {
  // The test page will register an event handler for orientation events,
  // expects to get an event with null values. The test raises a modal alert
  // dialog with a delay to test that the one-off null-event still propagates
  // to window after the alert is dismissed and the callback is invoked which
  // navigates to #pass.
  fetcher_->SetSensorDataAvailable(false);
  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);

  GURL test_url = GetTestUrl("device_sensors",
                             "device_orientation_null_test_with_alert.html");
  shell()->LoadURL(test_url);

  // TODO(timvolodine): investigate if it is possible to test this without
  // delay, crbug.com/360044.
  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));

  fetcher_->started_orientation_.Wait();
  fetcher_->stopped_orientation_.Wait();
  same_tab_observer.Wait();
  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}

// Flaking in the android try bot. See http://crbug.com/360578.
#if defined(OS_ANDROID) || defined(OS_WIN)
#define MAYBE_MotionNullTestWithAlert DISABLED_MotionNullTestWithAlert
#else
#define MAYBE_MotionNullTestWithAlert MotionNullTestWithAlert
#endif
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
    MAYBE_MotionNullTestWithAlert) {
  // The test page will register an event handler for motion events,
  // expects to get an event with null values. The test raises a modal alert
  // dialog with a delay to test that the one-off null-event still propagates
  // to window after the alert is dismissed and the callback is invoked which
  // navigates to #pass.
  fetcher_->SetSensorDataAvailable(false);
  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);

  GURL test_url =
      GetTestUrl("device_sensors", "device_motion_null_test_with_alert.html");
  shell()->LoadURL(test_url);

  // TODO(timvolodine): investigate if it is possible to test this without
  // delay, crbug.com/360044.
  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));

  fetcher_->started_motion_.Wait();
  fetcher_->stopped_motion_.Wait();
  same_tab_observer.Wait();
  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}

}  //  namespace

}  //  namespace content
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/policy/configuration_policy_provider.h"

#include "base/values.h"
#include "chrome/common/policy_constants.h"
#include "chrome/common/notification_service.h"

namespace {

// TODO(avi): Use this mapping to auto-generate MCX manifests and Windows
// ADM/ADMX files. http://crbug.com/49316

struct InternalPolicyValueMapEntry {
  ConfigurationPolicyStore::PolicyType policy_type;
  Value::ValueType value_type;
  const char* name;
};

const InternalPolicyValueMapEntry kPolicyValueMap[] = {
  { ConfigurationPolicyStore::kPolicyHomePage,
      Value::TYPE_STRING, policy::key::kHomepageLocation },
  { ConfigurationPolicyStore::kPolicyHomepageIsNewTabPage,
      Value::TYPE_BOOLEAN, policy::key::kHomepageIsNewTabPage },
  { ConfigurationPolicyStore::kPolicyRestoreOnStartup,
      Value::TYPE_INTEGER, policy::key::kRestoreOnStartup },
  { ConfigurationPolicyStore::kPolicyURLsToRestoreOnStartup,
      Value::TYPE_LIST, policy::key::kURLsToRestoreOnStartup },
  { ConfigurationPolicyStore::kPolicyProxyServerMode,
      Value::TYPE_INTEGER, policy::key::kProxyServerMode },
  { ConfigurationPolicyStore::kPolicyProxyServer,
      Value::TYPE_STRING, policy::key::kProxyServer },
  { ConfigurationPolicyStore::kPolicyProxyPacUrl,
      Value::TYPE_STRING, policy::key::kProxyPacUrl },
  { ConfigurationPolicyStore::kPolicyProxyBypassList,
      Value::TYPE_STRING, policy::key::kProxyBypassList },
  { ConfigurationPolicyStore::kPolicyAlternateErrorPagesEnabled,
      Value::TYPE_BOOLEAN, policy::key::kAlternateErrorPagesEnabled },
  { ConfigurationPolicyStore::kPolicySearchSuggestEnabled,
      Value::TYPE_BOOLEAN, policy::key::kSearchSuggestEnabled },
  { ConfigurationPolicyStore::kPolicyDnsPrefetchingEnabled,
      Value::TYPE_BOOLEAN, policy::key::kDnsPrefetchingEnabled },
  { ConfigurationPolicyStore::kPolicySafeBrowsingEnabled,
      Value::TYPE_BOOLEAN, policy::key::kSafeBrowsingEnabled },
  { ConfigurationPolicyStore::kPolicyMetricsReportingEnabled,
      Value::TYPE_BOOLEAN, policy::key::kMetricsReportingEnabled },
  { ConfigurationPolicyStore::kPolicyPasswordManagerEnabled,
      Value::TYPE_BOOLEAN, policy::key::kPasswordManagerEnabled },
  { ConfigurationPolicyStore::kPolicyPasswordManagerAllowShowPasswords,
      Value::TYPE_BOOLEAN, policy::key::kPasswordManagerAllowShowPasswords },
  { ConfigurationPolicyStore::kPolicyAutoFillEnabled,
      Value::TYPE_BOOLEAN, policy::key::kAutoFillEnabled },
  { ConfigurationPolicyStore::kPolicyDisabledPlugins,
      Value::TYPE_LIST, policy::key::kDisabledPlugins },
  { ConfigurationPolicyStore::kPolicyApplicationLocale,
      Value::TYPE_STRING, policy::key::kApplicationLocaleValue },
  { ConfigurationPolicyStore::kPolicySyncDisabled,
      Value::TYPE_BOOLEAN, policy::key::kSyncDisabled },
  { ConfigurationPolicyStore::kPolicyExtensionInstallAllowList,
      Value::TYPE_LIST, policy::key::kExtensionInstallAllowList },
  { ConfigurationPolicyStore::kPolicyExtensionInstallDenyList,
      Value::TYPE_LIST, policy::key::kExtensionInstallDenyList },
  { ConfigurationPolicyStore::kPolicyShowHomeButton,
      Value::TYPE_BOOLEAN, policy::key::kShowHomeButton },
};

}  // namespace

/* static */
const ConfigurationPolicyProvider::PolicyValueMap*
    ConfigurationPolicyProvider::PolicyValueMapping() {
  static PolicyValueMap* mapping;
  if (!mapping) {
    mapping = new PolicyValueMap();
    for (size_t i = 0; i < arraysize(kPolicyValueMap); ++i) {
      const InternalPolicyValueMapEntry& internal_entry = kPolicyValueMap[i];
      PolicyValueMapEntry entry;
      entry.policy_type = internal_entry.policy_type;
      entry.value_type = internal_entry.value_type;
      entry.name = std::string(internal_entry.name);
      mapping->push_back(entry);
    }
  }
  return mapping;
}

void ConfigurationPolicyProvider::NotifyStoreOfPolicyChange() {
  NotificationService::current()->Notify(
      NotificationType::POLICY_CHANGED,
      Source<ConfigurationPolicyProvider>(this),
      NotificationService::NoDetails());
}
<commit_msg>Update bug reference.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/policy/configuration_policy_provider.h"

#include "base/values.h"
#include "chrome/common/policy_constants.h"
#include "chrome/common/notification_service.h"

namespace {

// TODO(avi): Generate this mapping from the template metafile
// (chrome/app/policy/policy_templates.json). http://crbug.com/54711

struct InternalPolicyValueMapEntry {
  ConfigurationPolicyStore::PolicyType policy_type;
  Value::ValueType value_type;
  const char* name;
};

const InternalPolicyValueMapEntry kPolicyValueMap[] = {
  { ConfigurationPolicyStore::kPolicyHomePage,
      Value::TYPE_STRING, policy::key::kHomepageLocation },
  { ConfigurationPolicyStore::kPolicyHomepageIsNewTabPage,
      Value::TYPE_BOOLEAN, policy::key::kHomepageIsNewTabPage },
  { ConfigurationPolicyStore::kPolicyRestoreOnStartup,
      Value::TYPE_INTEGER, policy::key::kRestoreOnStartup },
  { ConfigurationPolicyStore::kPolicyURLsToRestoreOnStartup,
      Value::TYPE_LIST, policy::key::kURLsToRestoreOnStartup },
  { ConfigurationPolicyStore::kPolicyProxyServerMode,
      Value::TYPE_INTEGER, policy::key::kProxyServerMode },
  { ConfigurationPolicyStore::kPolicyProxyServer,
      Value::TYPE_STRING, policy::key::kProxyServer },
  { ConfigurationPolicyStore::kPolicyProxyPacUrl,
      Value::TYPE_STRING, policy::key::kProxyPacUrl },
  { ConfigurationPolicyStore::kPolicyProxyBypassList,
      Value::TYPE_STRING, policy::key::kProxyBypassList },
  { ConfigurationPolicyStore::kPolicyAlternateErrorPagesEnabled,
      Value::TYPE_BOOLEAN, policy::key::kAlternateErrorPagesEnabled },
  { ConfigurationPolicyStore::kPolicySearchSuggestEnabled,
      Value::TYPE_BOOLEAN, policy::key::kSearchSuggestEnabled },
  { ConfigurationPolicyStore::kPolicyDnsPrefetchingEnabled,
      Value::TYPE_BOOLEAN, policy::key::kDnsPrefetchingEnabled },
  { ConfigurationPolicyStore::kPolicySafeBrowsingEnabled,
      Value::TYPE_BOOLEAN, policy::key::kSafeBrowsingEnabled },
  { ConfigurationPolicyStore::kPolicyMetricsReportingEnabled,
      Value::TYPE_BOOLEAN, policy::key::kMetricsReportingEnabled },
  { ConfigurationPolicyStore::kPolicyPasswordManagerEnabled,
      Value::TYPE_BOOLEAN, policy::key::kPasswordManagerEnabled },
  { ConfigurationPolicyStore::kPolicyPasswordManagerAllowShowPasswords,
      Value::TYPE_BOOLEAN, policy::key::kPasswordManagerAllowShowPasswords },
  { ConfigurationPolicyStore::kPolicyAutoFillEnabled,
      Value::TYPE_BOOLEAN, policy::key::kAutoFillEnabled },
  { ConfigurationPolicyStore::kPolicyDisabledPlugins,
      Value::TYPE_LIST, policy::key::kDisabledPlugins },
  { ConfigurationPolicyStore::kPolicyApplicationLocale,
      Value::TYPE_STRING, policy::key::kApplicationLocaleValue },
  { ConfigurationPolicyStore::kPolicySyncDisabled,
      Value::TYPE_BOOLEAN, policy::key::kSyncDisabled },
  { ConfigurationPolicyStore::kPolicyExtensionInstallAllowList,
      Value::TYPE_LIST, policy::key::kExtensionInstallAllowList },
  { ConfigurationPolicyStore::kPolicyExtensionInstallDenyList,
      Value::TYPE_LIST, policy::key::kExtensionInstallDenyList },
  { ConfigurationPolicyStore::kPolicyShowHomeButton,
      Value::TYPE_BOOLEAN, policy::key::kShowHomeButton },
};

}  // namespace

/* static */
const ConfigurationPolicyProvider::PolicyValueMap*
    ConfigurationPolicyProvider::PolicyValueMapping() {
  static PolicyValueMap* mapping;
  if (!mapping) {
    mapping = new PolicyValueMap();
    for (size_t i = 0; i < arraysize(kPolicyValueMap); ++i) {
      const InternalPolicyValueMapEntry& internal_entry = kPolicyValueMap[i];
      PolicyValueMapEntry entry;
      entry.policy_type = internal_entry.policy_type;
      entry.value_type = internal_entry.value_type;
      entry.name = std::string(internal_entry.name);
      mapping->push_back(entry);
    }
  }
  return mapping;
}

void ConfigurationPolicyProvider::NotifyStoreOfPolicyChange() {
  NotificationService::current()->Notify(
      NotificationType::POLICY_CHANGED,
      Source<ConfigurationPolicyProvider>(this),
      NotificationService::NoDetails());
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <string>

#include <unistd.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <cstdlib>
#include <cstring>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"

#include "constants.h"
#include "network.h"
#include "helper_functions.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *>, ps_compare> procLocDict;
static list<server_function_info *> roundRobinList;
static list<server_info *> serverList;

static bool onSwitch = true;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void mapPrint(){
  cout << "procLocDict size: "<<procLocDict.size() << endl;
  cout << "Map Print: ";
  for(map<procedure_signature, list<server_info *>, ps_compare> ::const_iterator it = procLocDict.begin();
   it != procLocDict.end(); it++){

    cout << it->first.name << ", " ;
  }

  cout << endl;
}

void roundRobinPrint(){
  cout << "roundRobin Print: ";
  for(list<server_function_info *> ::const_iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    cout <<(*it)->si->server_identifier << ", "<<(*it)->si->port << ", "<<(*it)->ps->name << endl;
  }
}

void serverListPrint(){
  cout << "serverList Print: " << endl;
  for(list<server_info *> ::const_iterator it = serverList.begin(); it != serverList.end(); it++){
    cout << (*it)->server_identifier << ", " <<  (*it)->port << ", " <<  (*it)->socket<< endl;
  }
}

void registration_request_handler(RegisterRequestMessage * message, int sock){
  const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  cout << "We are trying to register: " << name  << ", " << server_identifier << ", " << port << endl;

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (procLocDict.find(key) == procLocDict.end()) {
    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    procLocDict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);
    server_function_info * info = new server_function_info(entry, newKey);

    //Adding to roundRobinList if server is not found
    roundRobinList.push_back(info);

    //Adding to serverList if server is not found
    bool serverExist = false;
    for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

      //if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        if( (*it)->port == entry->port &&  (*it)->socket == entry->socket){
          cout << "entry->port" << entry->port  << ", " << (*it)->port  << endl;
          serverExist = true;
          break;
        }
    }

    if(!serverExist){
      cout << "why doesnt this work" << endl;
      serverList.push_back(entry);
    }

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = procLocDict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->server_identifier == server_identifier && (*it)->port == port  && (*it)->socket == sock){
        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        cout << "Exact same proc and loc" << endl;
        sameLoc = true;
      }
    }

  	if(!sameLoc){ //same procedure different socket
      cout << "same proc different loc" << endl;

      server_info * new_msg_loc = new server_info(server_identifier, port, sock);
      hostList.push_back(new_msg_loc);

      int *newArgTypes = copyArgTypes(argTypes);

      procedure_signature * useFulKey = new procedure_signature(name, newArgTypes);
      server_function_info * info = new server_function_info(new_msg_loc, useFulKey);

      //Adding to roundRobinList if server is not found
      roundRobinList.push_back(info);

      //Adding to serverList if server is not found
      bool serverExist = false;
      for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

        //if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
          if( (*it)->port == new_msg_loc->port &&  (*it)->socket == new_msg_loc->socket){
            cout << "new_msg_loc->port" << new_msg_loc->port  << ", " << (*it)->port  << endl;
            serverExist = true;
            break;
          }
      }

      if(!serverExist){
        cout << "why doesnt this work" << endl;
        serverList.push_back(new_msg_loc);
      }
    }
  }

  //mapPrint();
  //roundRobinPrint();
  serverListPrint();

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

  cout << "sock: " << sock << endl;
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
void location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
  string serverIdToPushBack;
  int portToPushBack;
  int socketToPushBack;

  //cout << "Hunted name names: " << message->getName() << endl;

	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    //If the name are the same and argTypes
    //cout << "Iterator names: " << (*it)->ps->name << endl;

    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      cout << "Sending to server: " << (*it)->si->server_identifier << ", "<< (*it)->si->port<< endl;

      serverIdToPushBack = (*it)->si->server_identifier;
      portToPushBack = (*it)->si->port;
      socketToPushBack = (*it)->si->socket;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier.c_str(), (*it)->si->port);
      Segment locSuccessSeg = Segment(locSuccessMsg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      //When we have identified the correct procedure_signature use splice and move that service to the end
      //roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      break;
 		}
	}

  if(exist){

    list<server_function_info *>::iterator i = roundRobinList.begin();
    list<server_function_info *> tempList;

    while (i != roundRobinList.end()){
        //bool isActive = (*i)->update();
        //if((*it)->si->server_identifier == serverIdToPushBack && (*it)->si->port == portToPushBack && (*it)->si->socket == socketToPushBack){

        if ((*i)->si->port == portToPushBack && (*i)->si->socket == socketToPushBack){
            tempList.push_back(*i);
            roundRobinList.erase(i++);  // alternatively, i = items.erase(i);
        }else{
            ++i;
        }
    }

    roundRobinList.splice(roundRobinList.end(), tempList);

    roundRobinPrint();
  }else {
    int reasoncode = -5; // Need actual reasoncode
    LocFailureMessage locFailMsg = LocFailureMessage(reasoncode);
    Segment locFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    locFailSeg.send(sock);
  }
}

void binder_terminate_handler() {
  cout << "Binder set to execute" << endl;

  for (list<server_info *>::const_iterator it = serverList.begin(); it != serverList.end(); it++) {
    cout << "Terminating server: " << (*it)->server_identifier << ", " <<  (*it)->port << ", " <<  (*it)->socket<< endl;
    TerminateMessage termMsg = TerminateMessage();
    Segment termSeg = Segment(termMsg.getLength(), MSG_TYPE_TERMINATE, &termMsg);
    termSeg.send((*it)->socket);
    sleep(1);
  }

  onSwitch = false;

}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);

    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){

    //cout << "Loc Request" << endl;

    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);

    location_request_handler(lqm, sock);

  }else if (segment->getType() == MSG_TYPE_TERMINATE){

    cout << "Terminate Request" <<endl;

    binder_terminate_handler();
  }

	return retval;
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main() {
  fd_set allSockets;
  fd_set readSockets;

  /*
   * Clears all entries from the all sockets set and the read
   * sockets set
   */
  FD_ZERO(&allSockets);
  FD_ZERO(&readSockets);

  /*
   * Creates the welcome socket, adds it to the all sockets set and
   * sets it as the maximum socket so far
   */
  int welcomeSocket = createSocket();
  int status = setUpToListen(welcomeSocket);
  FD_SET(welcomeSocket, &allSockets);
  int maxSocket = welcomeSocket;

  /*
   * Prints the binder address and the binder port on the binder's
   * standard output
   */
  cout << "BINDER_ADDRESS " << getHostAddress() << endl;
  cout << "BINDER_PORT " << getSocketPort(welcomeSocket) << endl;

  while (onSwitch) {
    readSockets = allSockets;

    // Checks if some of the sockets are ready to be read from
    int result = select(maxSocket + 1, &readSockets, 0, 0, 0);
    if (result < 0) {
      continue;
    }

    for (int i = 0; i <= maxSocket; i++) {
      if (!FD_ISSET(i, &readSockets)) {
        continue;
      }

      if (i == welcomeSocket) {

        /*
         * Creates the connection socket when a connection is made
         * to the welcome socket
         */
        int connectionSocket = acceptConnection(i);
        if (connectionSocket < 0) {
          continue;
        }

        //cout << "WE heard from connectionSocket: " << connectionSocket << endl;
        // Adds the connection socket to the all sockets set
        FD_SET(connectionSocket, &allSockets);

        /*
         * Sets the connection socket as the maximum socket so far
         * if necessary
         */
        if (connectionSocket > maxSocket) {
          maxSocket = connectionSocket;
        }

      } else {

        /*
         * Creates a segment to receive data from the client/server and
         * reads into it from the connection socket
         */
        Segment *segment = 0;
        result = 0;
        result = Segment::receive(i, segment);
        if (result < 0) {
          /*
           * Closes the connection socket and removes it from the
           * all sockets set
           */
          destroySocket(i);
          FD_CLR(i, &allSockets);
          continue;
        }

        request_handler(segment, i);
      }
    }
  }

  // Destroys the welcome socket
  destroySocket(welcomeSocket);
}
<commit_msg>still doesnt work<commit_after>#include <iostream>
#include <sstream>
#include <string>

#include <unistd.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <cstdlib>
#include <cstring>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"

#include "constants.h"
#include "network.h"
#include "helper_functions.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *>, ps_compare> procLocDict;
static list<server_function_info *> roundRobinList;
static list<server_info *> serverList;

static bool onSwitch = true;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void mapPrint(){
  cout << "procLocDict size: "<<procLocDict.size() << endl;
  cout << "Map Print: ";
  for(map<procedure_signature, list<server_info *>, ps_compare> ::const_iterator it = procLocDict.begin();
   it != procLocDict.end(); it++){

    cout << it->first.name << ", " ;
  }

  cout << endl;
}

void roundRobinPrint(){
  cout << "roundRobin Print: ";
  for(list<server_function_info *> ::const_iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    cout <<(*it)->si->server_identifier << ", "<<(*it)->si->port << ", "<<(*it)->ps->name << endl;
  }
}

void serverListPrint(){
  cout << "serverList Print: " << endl;
  for(list<server_info *> ::const_iterator it = serverList.begin(); it != serverList.end(); it++){
    cout << (*it)->server_identifier << ", " <<  (*it)->port << ", " <<  (*it)->socket<< endl;
  }
}

void registration_request_handler(RegisterRequestMessage * message, int sock){
  const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  cout << "We are trying to register: " << name  << ", " << server_identifier << ", " << port << endl;

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (procLocDict.find(key) == procLocDict.end()) {
    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    procLocDict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);
    server_function_info * info = new server_function_info(entry, newKey);

    //Adding to roundRobinList if server is not found
    roundRobinList.push_back(info);

    //Adding to serverList if server is not found
    bool serverExist = false;
    for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

      //if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        if( (*it)->port == entry->port &&  (*it)->socket == entry->socket){
          cout << "entry->port" << entry->port  << ", " << (*it)->port  << endl;
          serverExist = true;
          break;
        }
    }

    if(!serverExist){
      cout << "why doesnt this work" << endl;
      serverList.push_back(entry);
    }

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = procLocDict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->server_identifier == server_identifier && (*it)->port == port  && (*it)->socket == sock){
        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        cout << "Exact same proc and loc" << endl;
        sameLoc = true;
      }
    }

  	if(!sameLoc){ //same procedure different socket
      cout << "same proc different loc" << endl;

      server_info * new_msg_loc = new server_info(server_identifier, port, sock);
      hostList.push_back(new_msg_loc);

      int *newArgTypes = copyArgTypes(argTypes);

      procedure_signature * useFulKey = new procedure_signature(name, newArgTypes);
      server_function_info * info = new server_function_info(new_msg_loc, useFulKey);

      //Adding to roundRobinList if server is not found
      roundRobinList.push_back(info);

      //Adding to serverList if server is not found
      bool serverExist = false;
      for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

        //if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
          if( (*it)->port == new_msg_loc->port &&  (*it)->socket == new_msg_loc->socket){
            cout << "new_msg_loc->port" << new_msg_loc->port  << ", " << (*it)->port  << endl;
            serverExist = true;
            break;
          }
      }

      if(!serverExist){
        cout << "why doesnt this work" << endl;
        serverList.push_back(new_msg_loc);
      }
    }
  }

  //mapPrint();
  //roundRobinPrint();
  serverListPrint();

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

  cout << "sock: " << sock << endl;
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
void location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
  string serverIdToPushBack;
  int portToPushBack;
  int socketToPushBack;

  //cout << "Hunted name names: " << message->getName() << endl;

	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    //If the name are the same and argTypes
    //cout << "Iterator names: " << (*it)->ps->name << endl;

    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      cout << "Sending to server: " << (*it)->si->server_identifier << ", "<< (*it)->si->port<< endl;

      serverIdToPushBack = (*it)->si->server_identifier;
      portToPushBack = (*it)->si->port;
      socketToPushBack = (*it)->si->socket;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier.c_str(), (*it)->si->port);
      Segment locSuccessSeg = Segment(locSuccessMsg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      //When we have identified the correct procedure_signature use splice and move that service to the end
      //roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      break;
 		}
	}

  if(exist){

    list<server_function_info *>::iterator i = roundRobinList.begin();
    list<server_function_info *> tempList;

    while (i != roundRobinList.end()){
        //bool isActive = (*i)->update();
        //if((*it)->si->server_identifier == serverIdToPushBack && (*it)->si->port == portToPushBack && (*it)->si->socket == socketToPushBack){
        if ((*i)->si->port == portToPushBack && (*i)->si->socket == socketToPushBack){
          tempList.push_back(*i);
          roundRobinList.erase(i++);  // alternatively, i = items.erase(i);
        }else{
          ++i;
        }
    }

    roundRobinList.splice(roundRobinList.end(), tempList);

    roundRobinPrint();
  }else {
    int reasoncode = -5; // Need actual reasoncode
    LocFailureMessage locFailMsg = LocFailureMessage(reasoncode);
    Segment locFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    locFailSeg.send(sock);
  }
}

void binder_terminate_handler() {
  cout << "Binder set to execute" << endl;

  for (list<server_info *>::const_iterator it = serverList.begin(); it != serverList.end(); it++) {
    cout << "Terminating server: " << (*it)->server_identifier << ", " <<  (*it)->port << ", " <<  (*it)->socket<< endl;
    TerminateMessage termMsg = TerminateMessage();
    Segment termSeg = Segment(termMsg.getLength(), MSG_TYPE_TERMINATE, &termMsg);
    termSeg.send((*it)->socket);
    sleep(1);
  }

  onSwitch = false;

}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);

    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){

    //cout << "Loc Request" << endl;

    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);

    location_request_handler(lqm, sock);

  }else if (segment->getType() == MSG_TYPE_TERMINATE){

    cout << "Terminate Request" <<endl;

    binder_terminate_handler();
  }

	return retval;
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main() {
  fd_set allSockets;
  fd_set readSockets;

  /*
   * Clears all entries from the all sockets set and the read
   * sockets set
   */
  FD_ZERO(&allSockets);
  FD_ZERO(&readSockets);

  /*
   * Creates the welcome socket, adds it to the all sockets set and
   * sets it as the maximum socket so far
   */
  int welcomeSocket = createSocket();
  int status = setUpToListen(welcomeSocket);
  FD_SET(welcomeSocket, &allSockets);
  int maxSocket = welcomeSocket;

  /*
   * Prints the binder address and the binder port on the binder's
   * standard output
   */
  cout << "BINDER_ADDRESS " << getHostAddress() << endl;
  cout << "BINDER_PORT " << getSocketPort(welcomeSocket) << endl;

  while (onSwitch) {
    readSockets = allSockets;

    // Checks if some of the sockets are ready to be read from
    int result = select(maxSocket + 1, &readSockets, 0, 0, 0);
    if (result < 0) {
      continue;
    }

    for (int i = 0; i <= maxSocket; i++) {
      if (!FD_ISSET(i, &readSockets)) {
        continue;
      }

      if (i == welcomeSocket) {

        /*
         * Creates the connection socket when a connection is made
         * to the welcome socket
         */
        int connectionSocket = acceptConnection(i);
        if (connectionSocket < 0) {
          continue;
        }

        //cout << "WE heard from connectionSocket: " << connectionSocket << endl;
        // Adds the connection socket to the all sockets set
        FD_SET(connectionSocket, &allSockets);

        /*
         * Sets the connection socket as the maximum socket so far
         * if necessary
         */
        if (connectionSocket > maxSocket) {
          maxSocket = connectionSocket;
        }

      } else {

        /*
         * Creates a segment to receive data from the client/server and
         * reads into it from the connection socket
         */
        Segment *segment = 0;
        result = 0;
        result = Segment::receive(i, segment);
        if (result < 0) {
          /*
           * Closes the connection socket and removes it from the
           * all sockets set
           */
          destroySocket(i);
          FD_CLR(i, &allSockets);
          continue;
        }

        request_handler(segment, i);
      }
    }
  }

  // Destroys the welcome socket
  destroySocket(welcomeSocket);
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <string>
#include <list>
#include <map>
#include <iostream>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"
#include "constants.h"
#include "network.h"
#include "helper_functions.h"

using namespace std;

// Global variables for binder
static map<procedure_signature, list<server_info *>, ps_compare> procLocDict;
static list<server_function_info *> roundRobinList;
static list<server_info *> serverList;
static bool isTerminated = false;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void mapPrint(){
  cout << "procLocDict size: "<<procLocDict.size() << endl;
  cout << "Map Print: ";
  for(map<procedure_signature, list<server_info *>, ps_compare> ::const_iterator it = procLocDict.begin();
   it != procLocDict.end(); it++){

    cout << it->first.name << ", " ;
  }

  cout << endl;
}

void roundRobinPrint(){
  cout << "roundRobin Print: ";
  for(list<server_function_info *> ::const_iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    cout <<(*it)->si->server_identifier << ", "<<(*it)->si->port << ", "<<(*it)->ps->name << endl;
  }
}

void serverListPrint(){
  cout << "serverList Print: " << endl;
  for(list<server_info *> ::const_iterator it = serverList.begin(); it != serverList.end(); it++){
    cout << (*it)->server_identifier << ", " <<  (*it)->port << ", " <<  (*it)->socket<< endl;
  }
}

// Handles a registration request from the server
void handleRegistrationRequest(RegisterRequestMessage *message, int sock) {
  const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  cout << "We are trying to register: " << name  << ", " << server_identifier << ", " << port << endl;

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (procLocDict.find(key) == procLocDict.end()) {

    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    procLocDict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);
    server_function_info * info = new server_function_info(entry, newKey);

    //Adding to roundRobinList if server is not found
    roundRobinList.push_back(info);

    //Adding to serverList if server is not found
    bool serverExist = false;
    for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

      cout << "(*it)->server_identifier" << (*it)->server_identifier << endl;
      cout << "entry->server_identifier" << entry->server_identifier << endl;

      if ((*it)->server_identifier == entry->server_identifier){
        cout << "The same " << endl;
      } else {
        cout << "is different" << endl;
      }

      if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        //if( (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        cout << "entry->port" << entry->port  << ", " << (*it)->port  << endl;
        serverExist = true;
        break;
      }
    }

    if (!serverExist) {
      serverList.push_back(entry);
    }

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = procLocDict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->server_identifier == server_identifier && (*it)->port == port  && (*it)->socket == sock){
      //if((*it)->port == port  && (*it)->socket == sock){

        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        cout << "Exact same proc and loc" << endl;
        sameLoc = true;
      }
    }

  	if (!sameLoc) { //same procedure different socket
      cout << "same proc different loc" << endl;

      server_info * new_msg_loc = new server_info(server_identifier, port, sock);
      hostList.push_back(new_msg_loc);

      int *newArgTypes = copyArgTypes(argTypes);

      procedure_signature * useFulKey = new procedure_signature(name, newArgTypes);
      server_function_info * info = new server_function_info(new_msg_loc, useFulKey);

      //Adding to roundRobinList if server is not found
      roundRobinList.push_back(info);

      //Adding to serverList if server is not found
      bool serverExist = false;
      for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

        if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        //if( (*it)->port == new_msg_loc->port &&  (*it)->socket == new_msg_loc->socket){
            cout << "new_msg_loc->port" << new_msg_loc->port  << ", " << (*it)->port  << endl;
            serverExist = true;
            break;
          }
      }

      if (!serverExist) {
        serverList.push_back(new_msg_loc);
      }
    }
  }

  serverListPrint();

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

  cout << "sock: " << sock << endl;
}

// Handles a location request from the client
void handleLocationRequest(LocRequestMessage *message, int sock) {
  bool exist = false;
  string serverIdToPushBack;
  int portToPushBack;
  int socketToPushBack;

	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    //If the name are the same and argTypes

    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      cout << "Sending to server: " << (*it)->si->server_identifier << ", "<< (*it)->si->port<< endl;

      serverIdToPushBack = (*it)->si->server_identifier;
      portToPushBack = (*it)->si->port;
      socketToPushBack = (*it)->si->socket;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier.c_str(), (*it)->si->port);
      Segment locSuccessSeg = Segment(locSuccessMsg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      break;
 		}
	}

  if (exist) {

    list<server_function_info *>::iterator i = roundRobinList.begin();
    list<server_function_info *> tempList;

    while (i != roundRobinList.end()){
        //bool isActive = (*i)->update();
        if((*i)->si->server_identifier == serverIdToPushBack && (*i)->si->port == portToPushBack && (*i)->si->socket == socketToPushBack){
        //if ((*i)->si->port == portToPushBack && (*i)->si->socket == socketToPushBack){
          tempList.push_back(*i);
          roundRobinList.erase(i++);  // alternatively, i = items.erase(i);
        }else{
          ++i;
        }
    }

    roundRobinList.splice(roundRobinList.end(), tempList);

    roundRobinPrint();
  } else {
    LocFailureMessage locFailMsg =
      LocFailureMessage(ERROR_CODE_PROCEDURE_NOT_FOUND);
    Segment locFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    locFailSeg.send(sock);
  }
}

// Handles a termination request from the client
void handleTerminationRequest() {
  // Informs all the servers to terminate
  for (list<server_info *>::const_iterator it = serverList.begin(); it != serverList.end(); it++) {
    cout << "Terminating server: " << (*it)->server_identifier;
    cout << ", " <<  (*it)->port;
    cout << ", " <<  (*it)->socket << endl;
    TerminateMessage messageToServer = TerminateMessage();
    Segment segmentToServer =
      Segment(messageToServer.getLength(), MSG_TYPE_TERMINATE,
        &messageToServer);
    segmentToServer.send((*it)->socket);
  }

  // Signals the binder to terminate
  isTerminated = true;
}

// Handles a request from the client/server
void handleRequest(Segment *segment, int socket) {
  switch (segment->getType()) {
    case MSG_TYPE_REGISTER_REQUEST: {
      RegisterRequestMessage *messageFromServer =
        dynamic_cast<RegisterRequestMessage *>(segment->getMessage());
      handleRegistrationRequest(messageFromServer, socket);
      break;
    }

    case MSG_TYPE_LOC_REQUEST: {
      LocRequestMessage *messageFromClient =
        dynamic_cast<LocRequestMessage *>(segment->getMessage());
      handleLocationRequest(messageFromClient, socket);
      break;
    }

    case MSG_TYPE_TERMINATE: {
      handleTerminationRequest();
      break;
    }
  }
}

int main() {
  fd_set allSockets;
  fd_set readSockets;

  /*
   * Clears all entries from the all sockets set and the read
   * sockets set
   */
  FD_ZERO(&allSockets);
  FD_ZERO(&readSockets);

  /*
   * Creates the welcome socket, adds it to the all sockets set and
   * sets it as the maximum socket so far
   */
  int welcomeSocket = createSocket();
  if (welcomeSocket < 0) {
    return welcomeSocket;
  }
  int result = setUpToListen(welcomeSocket);
  if (result < 0) {
    return result;
  }
  FD_SET(welcomeSocket, &allSockets);
  int maxSocket = welcomeSocket;

  /*
   * Prints the binder address and the binder port on the binder's
   * standard output
   */
  string binderIdentifier = getHostAddress();
  if (binderIdentifier == "") {
    return ERROR_CODE_HOST_ADDRESS_NOT_FOUND;
  }
  int port = getSocketPort(welcomeSocket);
  if (port < 0) {
    return port;
  }
  cout << "BINDER_ADDRESS " << binderIdentifier << endl;
  cout << "BINDER_PORT " << port << endl;

  while (!isTerminated) {
    readSockets = allSockets;

    // Checks if some of the sockets are ready to be read from
    int result = select(maxSocket + 1, &readSockets, 0, 0, 0);
    if (result < 0) {
      continue;
    }

    for (int i = 0; i <= maxSocket; i++) {
      if (!FD_ISSET(i, &readSockets)) {
        continue;
      }

      if (i == welcomeSocket) {

        /*
         * Creates the connection socket when a connection is made
         * to the welcome socket
         */
        int connectionSocket = acceptConnection(i);
        if (connectionSocket < 0) {
          continue;
        }

        // Adds the connection socket to the all sockets set
        FD_SET(connectionSocket, &allSockets);

        /*
         * Sets the connection socket as the maximum socket so far
         * if necessary
         */
        if (connectionSocket > maxSocket) {
          maxSocket = connectionSocket;
        }

      } else {

        /*
         * Creates a segment to receive data from the client/server and
         * reads into it from the connection socket
         */
        Segment *segment = 0;
        result = 0;
        result = Segment::receive(i, segment);
        if (result < 0) {
          /*
           * Closes the connection socket and removes it from the
           * all sockets set
           */
          destroySocket(i);
          FD_CLR(i, &allSockets);
          continue;
        }

        // Handles a request from the client/server
        handleRequest(segment, i);
      }
    }
  }

  // Destroys the welcome socket
  destroySocket(welcomeSocket);

  return SUCCESS_CODE;
}
<commit_msg>cleaning up<commit_after>#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <string>
#include <list>
#include <map>
#include <iostream>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"
#include "constants.h"
#include "network.h"
#include "helper_functions.h"

using namespace std;

// Global variables for binder
static map<procedure_signature, list<server_info *>, ps_compare> procLocDict;
static list<server_function_info *> roundRobinList;
static list<server_info *> serverList;
static bool isTerminated = false;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void mapPrint(){
  cout << "procLocDict size: "<<procLocDict.size() << endl;
  cout << "Map Print: ";
  for(map<procedure_signature, list<server_info *>, ps_compare> ::const_iterator it = procLocDict.begin();
   it != procLocDict.end(); it++){

    cout << it->first.name << ", " ;
  }

  cout << endl;
}

void roundRobinPrint(){
  cout << "roundRobin Print: ";
  for(list<server_function_info *> ::const_iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    cout <<(*it)->si->server_identifier << ", "<<(*it)->si->port << ", "<<(*it)->ps->name << endl;
  }
}

void serverListPrint(){
  cout << "serverList Print: " << endl;
  for(list<server_info *> ::const_iterator it = serverList.begin(); it != serverList.end(); it++){
    cout << (*it)->server_identifier << ", " <<  (*it)->port << ", " <<  (*it)->socket<< endl;
  }
}

// Handles a registration request from the server
void handleRegistrationRequest(RegisterRequestMessage *message, int sock) {
  const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  cout << "We are trying to register: " << name  << ", " << server_identifier << ", " << port << endl;

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (procLocDict.find(key) == procLocDict.end()) {

    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    procLocDict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);
    server_function_info * info = new server_function_info(entry, newKey);

    //Adding to roundRobinList if server is not found
    roundRobinList.push_back(info);

    //Adding to serverList if server is not found
    bool serverExist = false;
    for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

      cout << "(*it)->server_identifier" << (*it)->server_identifier << endl;
      cout << "entry->server_identifier" << entry->server_identifier << endl;

      if ((*it)->server_identifier == entry->server_identifier){
        cout << "The same " << endl;
      } else {
        cout << "is different" << endl;
      }

      if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        //if( (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        cout << "entry->port" << entry->port  << ", " << (*it)->port  << endl;
        serverExist = true;
        break;
      }
    }

    if (!serverExist) {
      serverList.push_back(entry);
    }

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = procLocDict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->server_identifier == server_identifier && (*it)->port == port  && (*it)->socket == sock){
      //if((*it)->port == port  && (*it)->socket == sock){

        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        cout << "Exact same proc and loc" << endl;
        sameLoc = true;
      }
    }

  	if (!sameLoc) { //same procedure different socket
      cout << "same proc different loc" << endl;

      server_info * new_msg_loc = new server_info(server_identifier, port, sock);
      hostList.push_back(new_msg_loc);

      int *newArgTypes = copyArgTypes(argTypes);

      procedure_signature * useFulKey = new procedure_signature(name, newArgTypes);
      server_function_info * info = new server_function_info(new_msg_loc, useFulKey);

      //Adding to roundRobinList if server is not found
      roundRobinList.push_back(info);

      //Adding to serverList if server is not found
      bool serverExist = false;
      for (list<server_info *>::iterator it = serverList.begin(); it != serverList.end(); it++) {

        if( (*it)->server_identifier == entry->server_identifier && (*it)->port == entry->port &&  (*it)->socket == entry->socket){
        //if( (*it)->port == new_msg_loc->port &&  (*it)->socket == new_msg_loc->socket){
            cout << "new_msg_loc->port" << new_msg_loc->port  << ", " << (*it)->port  << endl;
            serverExist = true;
            break;
          }
      }

      if (!serverExist) {
        serverList.push_back(new_msg_loc);
      }
    }
  }

  //serverListPrint();

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

  cout << "sock: " << sock << endl;
}

// Handles a location request from the client
void handleLocationRequest(LocRequestMessage *message, int sock) {
  bool exist = false;
  string serverIdToPushBack;
  int portToPushBack;
  int socketToPushBack;

	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    //If the name are the same and argTypes

    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      cout << "Sending to server: " << (*it)->si->server_identifier << ", "<< (*it)->si->port<< endl;

      serverIdToPushBack = (*it)->si->server_identifier;
      portToPushBack = (*it)->si->port;
      socketToPushBack = (*it)->si->socket;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier.c_str(), (*it)->si->port);
      Segment locSuccessSeg = Segment(locSuccessMsg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      break;
 		}
	}

  if (exist) {

    list<server_function_info *>::iterator i = roundRobinList.begin();
    list<server_function_info *> tempList;

    while (i != roundRobinList.end()){
        //bool isActive = (*i)->update();
        if((*i)->si->server_identifier == serverIdToPushBack && (*i)->si->port == portToPushBack && (*i)->si->socket == socketToPushBack){
        //if ((*i)->si->port == portToPushBack && (*i)->si->socket == socketToPushBack){
          tempList.push_back(*i);
          roundRobinList.erase(i++);  // alternatively, i = items.erase(i);
        }else{
          ++i;
        }
    }

    roundRobinList.splice(roundRobinList.end(), tempList);

    //roundRobinPrint();

  } else {
    LocFailureMessage locFailMsg =
      LocFailureMessage(ERROR_CODE_PROCEDURE_NOT_FOUND);
    Segment locFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    locFailSeg.send(sock);
  }
}

// Handles a termination request from the client
void handleTerminationRequest() {
  // Informs all the servers to terminate
  for (list<server_info *>::const_iterator it = serverList.begin(); it != serverList.end(); it++) {
    cout << "Terminating server: " << (*it)->server_identifier;
    cout << ", " <<  (*it)->port;
    cout << ", " <<  (*it)->socket << endl;
    TerminateMessage messageToServer = TerminateMessage();
    Segment segmentToServer =
      Segment(messageToServer.getLength(), MSG_TYPE_TERMINATE,
        &messageToServer);
    segmentToServer.send((*it)->socket);
  }

  // Signals the binder to terminate
  isTerminated = true;
}

// Handles a request from the client/server
void handleRequest(Segment *segment, int socket) {
  switch (segment->getType()) {
    case MSG_TYPE_REGISTER_REQUEST: {
      RegisterRequestMessage *messageFromServer =
        dynamic_cast<RegisterRequestMessage *>(segment->getMessage());
      handleRegistrationRequest(messageFromServer, socket);
      break;
    }

    case MSG_TYPE_LOC_REQUEST: {
      LocRequestMessage *messageFromClient =
        dynamic_cast<LocRequestMessage *>(segment->getMessage());
      handleLocationRequest(messageFromClient, socket);
      break;
    }

    case MSG_TYPE_TERMINATE: {
      handleTerminationRequest();
      break;
    }
  }
}

int main() {
  fd_set allSockets;
  fd_set readSockets;

  /*
   * Clears all entries from the all sockets set and the read
   * sockets set
   */
  FD_ZERO(&allSockets);
  FD_ZERO(&readSockets);

  /*
   * Creates the welcome socket, adds it to the all sockets set and
   * sets it as the maximum socket so far
   */
  int welcomeSocket = createSocket();
  if (welcomeSocket < 0) {
    return welcomeSocket;
  }
  int result = setUpToListen(welcomeSocket);
  if (result < 0) {
    return result;
  }
  FD_SET(welcomeSocket, &allSockets);
  int maxSocket = welcomeSocket;

  /*
   * Prints the binder address and the binder port on the binder's
   * standard output
   */
  string binderIdentifier = getHostAddress();
  if (binderIdentifier == "") {
    return ERROR_CODE_HOST_ADDRESS_NOT_FOUND;
  }
  int port = getSocketPort(welcomeSocket);
  if (port < 0) {
    return port;
  }
  cout << "BINDER_ADDRESS " << binderIdentifier << endl;
  cout << "BINDER_PORT " << port << endl;

  while (!isTerminated) {
    readSockets = allSockets;

    // Checks if some of the sockets are ready to be read from
    int result = select(maxSocket + 1, &readSockets, 0, 0, 0);
    if (result < 0) {
      continue;
    }

    for (int i = 0; i <= maxSocket; i++) {
      if (!FD_ISSET(i, &readSockets)) {
        continue;
      }

      if (i == welcomeSocket) {

        /*
         * Creates the connection socket when a connection is made
         * to the welcome socket
         */
        int connectionSocket = acceptConnection(i);
        if (connectionSocket < 0) {
          continue;
        }

        // Adds the connection socket to the all sockets set
        FD_SET(connectionSocket, &allSockets);

        /*
         * Sets the connection socket as the maximum socket so far
         * if necessary
         */
        if (connectionSocket > maxSocket) {
          maxSocket = connectionSocket;
        }

      } else {

        /*
         * Creates a segment to receive data from the client/server and
         * reads into it from the connection socket
         */
        Segment *segment = 0;
        result = 0;
        result = Segment::receive(i, segment);
        if (result < 0) {
          /*
           * Closes the connection socket and removes it from the
           * all sockets set
           */
          destroySocket(i);
          FD_CLR(i, &allSockets);
          continue;
        }

        // Handles a request from the client/server
        handleRequest(segment, i);
      }
    }
  }

  // Destroys the welcome socket
  destroySocket(welcomeSocket);

  return SUCCESS_CODE;
}
<|endoftext|>