Index: /trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp	(revision 23632)
+++ /trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp	(revision 23633)
@@ -45,5 +45,5 @@
  * Argument package for Console::migrationServeConnection.
  */
-typedef struct MIGRATIONSERVEARGS
+typedef struct MIGRATIONSTATE
 {
     Console    *pConsole;
@@ -51,7 +51,10 @@
     PVM         pVM;
     const char *pszPassword;
-    RTTIMERLR   hTimer;
-} MIGRATIONSERVEARGS;
-typedef MIGRATIONSERVEARGS *PMIGRATIONSERVEARGS;
+    void       *pvVMCallbackTask;
+    RTSOCKET    hSocket;
+    uint64_t    offStream;
+    int         rc;
+} MIGRATIONSTATE;
+typedef MIGRATIONSTATE *PMIGRATIONSTATE;
 
 
@@ -62,4 +65,88 @@
 
 
+/**
+ * @copydoc SSMSTRMOPS::pfnWrite
+ */
+static DECLCALLBACK(int) migrationTcpOpWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite)
+{
+    PMIGRATIONSTATE pState = (PMIGRATIONSTATE)pvUser;
+    int rc = RTTcpWrite(pState->hSocket, pvBuf, cbToWrite);
+    if (RT_SUCCESS(rc))
+    {
+        pState->offStream += cbToWrite;
+        return VINF_SUCCESS;
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc SSMSTRMOPS::pfnRead
+ */
+static DECLCALLBACK(int) migrationTcpOpRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead)
+{
+    PMIGRATIONSTATE pState = (PMIGRATIONSTATE)pvUser;
+    int rc = RTTcpRead(pState->hSocket, pvBuf, cbToRead, pcbRead);
+    if (RT_SUCCESS(rc))
+    {
+        pState->offStream += pcbRead ? *pcbRead : cbToRead;
+        return VINF_SUCCESS;
+    }
+    return rc;
+}
+
+
+/**
+ * @copydoc SSMSTRMOPS::pfnSeek
+ */
+static DECLCALLBACK(int) migrationTcpOpSeek(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
+{
+    return VERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * @copydoc SSMSTRMOPS::pfnTell
+ */
+static DECLCALLBACK(uint64_t) migrationTcpOpTell(void *pvUser)
+{
+    PMIGRATIONSTATE pState = (PMIGRATIONSTATE)pvUser;
+    return pState->offStream;
+}
+
+
+/**
+ * @copydoc SSMSTRMOPS::pfnSize
+ */
+static DECLCALLBACK(int) migrationTcpOpSize(void *pvUser, uint64_t *pcb)
+{
+    return VERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * @copydoc SSMSTRMOPS::pfnClose
+ */
+static DECLCALLBACK(int) migrationTcpOpClose(void *pvUser)
+{
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Method table for a TCP based stream.
+ */
+static SSMSTRMOPS const g_migrationTcpOps =
+{
+    SSMSTRMOPS_VERSION,
+    migrationTcpOpWrite,
+    migrationTcpOpRead,
+    migrationTcpOpSeek,
+    migrationTcpOpTell,
+    migrationTcpOpSize,
+    migrationTcpOpClose,
+    SSMSTRMOPS_VERSION
+};
+
 
 /**
@@ -73,7 +160,25 @@
 
 
+/**
+ * Start live migration to the specified target.
+ *
+ * @returns COM status code.
+ *
+ * @param   aHostname   The name of the target host.
+ * @param   aPort       The TCP port number.
+ * @param   aPassword   The password.
+ * @param   aProgress   Where to return the progress object.
+ */
 STDMETHODIMP
 Console::Migrate(IN_BSTR aHostname, ULONG aPort, IN_BSTR aPassword, IProgress **aProgress)
 {
+    /*
+     * Validate parameters.
+     */
+
+    /*
+     * Try change the state, create a progress object and spawn a worker thread.
+     */
+
     return E_FAIL;
 }
@@ -87,7 +192,9 @@
  * @param   pVM                 The VM handle
  * @param   pMachine            The IMachine for the virtual machine.
+ * @param   pvVMCallbackTask    The callback task pointer for
+ *                              stateProgressCallback().
  */
 int
-Console::migrationLoadRemote(PVM pVM, IMachine *pMachine)
+Console::migrationLoadRemote(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask)
 {
     /*
@@ -140,11 +247,11 @@
 
     /*
-     * Create a timer for timing out after 5 mins.
-     */
-    RTTIMERLR hTimer;
-    rc = RTTimerLRCreateEx(&hTimer, 0, 0, migrationTimeout, hServer);
+     * Create a one-shot timer for timing out after 5 mins.
+     */
+    RTTIMERLR hTimerLR;
+    rc = RTTimerLRCreateEx(&hTimerLR, 0 /*ns*/, RTTIMER_FLAGS_CPU_ANY, migrationTimeout, hServer);
     if (RT_SUCCESS(rc))
     {
-        rc = RTTimerLRStart(hTimer, 5*60*UINT64_C(1000000000) /*ns*/);
+        rc = RTTimerLRStart(hTimerLR, 5*60*UINT64_C(1000000000) /*ns*/);
         if (RT_SUCCESS(rc))
         {
@@ -152,14 +259,21 @@
              * Do the job, when it returns we're done.
              */
-            MIGRATIONSERVEARGS Args;
-            Args.pConsole    = this;
-            Args.pMachine    = pMachine;
-            Args.pVM         = pVM;
-            Args.pszPassword = strPassword.c_str();
-            Args.hTimer      = hTimer;
-            rc = RTTcpServerListen(hServer, Console::migrationServeConnection, &Args);
-        }
-
-        RTTimerLRDestroy(hTimer);
+            MIGRATIONSTATE State;
+            State.pConsole      = this;
+            State.pMachine      = pMachine;
+            State.pVM           = pVM;
+            State.pszPassword   = strPassword.c_str();
+            State.hSocket       = NIL_RTSOCKET;
+            State.offStream     = UINT64_MAX / 2;
+            State.rc            = VINF_SUCCESS;
+
+            rc = RTTcpServerListen(hServer, Console::migrationServeConnection, &State);
+            if (rc == VERR_TCP_SERVER_STOP)
+                rc = State.rc;
+            if (RT_FAILURE(rc))
+                LogRel(("Migration: RTTcpServerListen -> %Rrc\n", rc));
+        }
+
+        RTTimerLRDestroy(hTimerLR);
     }
     RTTcpServerDestroy(hServer);
@@ -167,4 +281,5 @@
     return rc;
 }
+
 
 /**
@@ -215,9 +330,7 @@
 Console::migrationServeConnection(RTSOCKET Sock, void *pvUser)
 {
-    PMIGRATIONSERVEARGS pArgs       = (PMIGRATIONSERVEARGS)pvUser;
-    Console            *pConsole    = pArgs->pConsole;
-    IMachine           *pMachine    = pArgs->pMachine;
-    PVM                 pVM         = pArgs->pVM;
-    const char         *pszPassword = pArgs->pszPassword;
+    PMIGRATIONSTATE pState   = (PMIGRATIONSTATE)pvUser;
+    Console        *pConsole = pState->pConsole;
+    IMachine       *pMachine = pState->pMachine;
 
     /*
@@ -236,5 +349,6 @@
      * this is the last connection attempt).
      */
-    unsigned off = 0;
+    const char *pszPassword = pState->pszPassword;
+    unsigned    off = 0;
     while (pszPassword[off])
     {
@@ -256,4 +370,5 @@
      * Command processing loop.
      */
+    pState->hSocket = Sock;
     for (;;)
     {
@@ -263,8 +378,17 @@
             break;
 
-        if (!strcmp(szCmd, "state"))
-        {
-            /* restore the state. */
-        }
+        if (!strcmp(szCmd, "load"))
+        {
+            pState->offStream = 0;
+            rc = VMR3LoadFromStream(pState->pVM, &g_migrationTcpOps, pState,
+                                    Console::stateProgressCallback, pState->pvVMCallbackTask);
+            if (RT_FAILURE(rc))
+            {
+                LogRel(("Migration: VMR3LoadFromStream -> %Rrc\n", rc));
+                break;
+            }
+        }
+        /** @todo implement config verification and hardware compatability checks. Or
+         *        maybe leave part of these to the saved state machinery? */
         else if (!strcmp(szCmd, "done"))
             break;
@@ -275,4 +399,5 @@
         }
     }
+    pState->hSocket = NIL_RTSOCKET;
 
     return VERR_TCP_SERVER_STOP;
Index: /trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 23632)
+++ /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 23633)
@@ -6728,5 +6728,5 @@
                 else if (task->mLiveMigrationTarget)
                     /* -> ConsoleImpl-LiveMigration.cpp */
-                    vrc = console->migrationLoadRemote(pVM, pMachine);
+                    vrc = console->migrationLoadRemote(pVM, pMachine, static_cast<VMProgressTask*>(task.get()));
                 else if (task->mStartPaused)
                     /* done */
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 23632)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 23633)
@@ -514,5 +514,5 @@
     /** @name Live migration support
      * @{ */
-    int                         migrationLoadRemote(PVM pVM, IMachine *pMachine);
+    int                         migrationLoadRemote(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask);
     static DECLCALLBACK(int)    migrationServeConnection(RTSOCKET Sock, void *pvUser);
     /** @} */
