From 6be8f6b06c82b393c2da19219b17b68918187ae0 Mon Sep 17 00:00:00 2001
From: Guy Zana <guy@cloudius-systems.com>
Date: Sun, 8 Sep 2013 13:58:51 +0300
Subject: [PATCH] DHCP: add an option to wait for an IP and make it the default

---
 core/dhcp.cc           | 22 ++++++++++++++++++----
 include/dhcp.hh        | 10 +++++++++-
 java/jni/networking.cc |  4 ++--
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/core/dhcp.cc b/core/dhcp.cc
index f39cc2085..77b5e6b27 100644
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -40,10 +40,10 @@ extern "C" int dhcp_hook_rx(struct mbuf* m)
     return 1;
 }
 
-extern "C" void dhcp_start()
+void dhcp_start(bool wait)
 {
     // Initialize the global DHCP worker
-    net_dhcp_worker.init();
+    net_dhcp_worker.init(wait);
 }
 
 namespace dhcp {
@@ -503,7 +503,7 @@ namespace dhcp {
     ///////////////////////////////////////////////////////////////////////////
 
     dhcp_worker::dhcp_worker()
-        : _dhcp_thread(nullptr)
+        : _dhcp_thread(nullptr), _have_ip(false), _waiter(nullptr)
     {
 
     }
@@ -517,7 +517,7 @@ namespace dhcp {
         // FIXME: free packets and states
     }
 
-    void dhcp_worker::init()
+    void dhcp_worker::init(bool wait)
     {
         struct ifnet *ifp = nullptr;
 
@@ -542,6 +542,12 @@ namespace dhcp {
         // Create the worker thread
         _dhcp_thread = new sched::thread([&] { dhcp_worker_fn(); });
         _dhcp_thread->start();
+
+        if (wait) {
+            dhcp_i("Waiting for IP...");
+            _waiter = sched::thread::current();
+            sched::thread::wait_until([&]{ return _have_ip; });
+        }
     }
 
     void dhcp_worker::dhcp_worker_fn()
@@ -565,6 +571,14 @@ namespace dhcp {
             }
 
             it->second->process_packet(m);
+
+            // Check if we got an ip
+            if (it->second->is_acknowledged()) {
+                _have_ip = true;
+                if (_waiter) {
+                    _waiter->wake();
+                }
+            }
         }
     }
 
diff --git a/include/dhcp.hh b/include/dhcp.hh
index 6e1da5f19..cf5797497 100644
--- a/include/dhcp.hh
+++ b/include/dhcp.hh
@@ -11,6 +11,8 @@
 #include <osv/mutex.h>
 #include <osv/debug.h>
 
+extern "C" void dhcp_start(bool wait);
+
 namespace dhcp {
 
     #define dhcp_tag "dhcp"
@@ -195,6 +197,8 @@ namespace dhcp {
         void state_discover(dhcp_mbuf &dm);
         void state_request(dhcp_mbuf &dm);
 
+        bool is_acknowledged() { return (_state == DHCP_ACKNOWLEDGE); }
+
     private:
         state _state;
         struct ifnet* _ifp;
@@ -212,7 +216,7 @@ namespace dhcp {
         ~dhcp_worker();
 
         // Initializing a state per interface, sends discover packets
-        void init();
+        void init(bool wait);
 
         void dhcp_worker_fn();
         void queue_packet(struct mbuf* m);
@@ -223,6 +227,10 @@ namespace dhcp {
         mutex _lock;
         std::list<struct mbuf*> _rx_packets;
         std::map<struct ifnet*, dhcp_interface_state*> _universe;
+
+        // Wait for IP
+        bool _have_ip;
+        sched::thread * _waiter;
     };
 
 } // namespace dhcp
diff --git a/java/jni/networking.cc b/java/jni/networking.cc
index a695edbf0..3e05147bc 100644
--- a/java/jni/networking.cc
+++ b/java/jni/networking.cc
@@ -78,7 +78,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_cloudius_net_Route_add_1default
     env->ReleaseStringUTFChars(gw, gw_c);
 }
 
-extern "C" void dhcp_start();
+extern "C" void dhcp_start(bool wait);
 
 /*
  * Class:     com_cloudius_net_DHCP
@@ -88,6 +88,6 @@ extern "C" void dhcp_start();
 extern "C" JNIEXPORT void JNICALL Java_com_cloudius_net_DHCP_dhcp_1start
   (JNIEnv *, jclass)
 {
-    dhcp_start();
+    dhcp_start(true);
 }
 
-- 
GitLab