ConsoleImpl-LiveMigration.cpp revision bc0a19dc73b33c7e92288cc85eab1a5c1d459f3f
af84459fbf938e508fd10b01cb8d699c79083813takashi/* $Id$ */
af84459fbf938e508fd10b01cb8d699c79083813takashi/** @file
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * VBox Console COM Class implementation, The Live Migration Part.
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd */
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd
af84459fbf938e508fd10b01cb8d699c79083813takashi/*
af84459fbf938e508fd10b01cb8d699c79083813takashi * Copyright (C) 2009 Sun Microsystems, Inc.
af84459fbf938e508fd10b01cb8d699c79083813takashi *
af84459fbf938e508fd10b01cb8d699c79083813takashi * This file is part of VirtualBox Open Source Edition (OSE), as
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * available from http://www.virtualbox.org. This file is free software;
af84459fbf938e508fd10b01cb8d699c79083813takashi * you can redistribute it and/or modify it under the terms of the GNU
af84459fbf938e508fd10b01cb8d699c79083813takashi * General Public License (GPL) as published by the Free Software
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * Foundation, in version 2 as it comes in the "COPYING" file of the
2e545ce2450a9953665f701bb05350f0d3f26275nd * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen *
af84459fbf938e508fd10b01cb8d699c79083813takashi * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
af84459fbf938e508fd10b01cb8d699c79083813takashi * Clara, CA 95054 USA or visit http://www.sun.com if you need
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * additional information or have any questions.
3f08db06526d6901aa08c110b5bc7dde6bc39905nd */
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi/*******************************************************************************
af84459fbf938e508fd10b01cb8d699c79083813takashi* Header Files *
3f08db06526d6901aa08c110b5bc7dde6bc39905nd*******************************************************************************/
af84459fbf938e508fd10b01cb8d699c79083813takashi#include "ConsoleImpl.h"
af84459fbf938e508fd10b01cb8d699c79083813takashi#include "Logging.h"
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung
af84459fbf938e508fd10b01cb8d699c79083813takashi#include <iprt/err.h>
0a05fab9aadd37834734ffe106fc8ad4488fb3e3rbowen#include <iprt/rand.h>
0a05fab9aadd37834734ffe106fc8ad4488fb3e3rbowen#include <iprt/tcp.h>
af84459fbf938e508fd10b01cb8d699c79083813takashi#include <iprt/timer.h>
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi#include <VBox/vmapi.h>
af84459fbf938e508fd10b01cb8d699c79083813takashi#include <VBox/ssm.h>
3c13a815670b54d1c17bf02954f7d2b066cde95cnd#include <VBox/err.h>
3c13a815670b54d1c17bf02954f7d2b066cde95cnd#include <VBox/version.h>
2d39a41e98476f5235b7c37ce745a4aa0904b1cbrbowen#include <VBox/com/string.h>
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe/*******************************************************************************
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe* Structures and Typedefs *
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe*******************************************************************************/
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe/**
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen * Argument package for Console::migrationServeConnection.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowetypedef struct MIGRATIONSERVEARGS
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi Console *pConsole;
af84459fbf938e508fd10b01cb8d699c79083813takashi IMachine *pMachine;
af84459fbf938e508fd10b01cb8d699c79083813takashi PVM pVM;
af84459fbf938e508fd10b01cb8d699c79083813takashi const char *pszPassword;
af84459fbf938e508fd10b01cb8d699c79083813takashi RTTIMERLR hTimer;
af84459fbf938e508fd10b01cb8d699c79083813takashi} MIGRATIONSERVEARGS;
af84459fbf938e508fd10b01cb8d699c79083813takashitypedef MIGRATIONSERVEARGS *PMIGRATIONSERVEARGS;
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi/*******************************************************************************
af84459fbf938e508fd10b01cb8d699c79083813takashi* Global Variables *
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe*******************************************************************************/
af84459fbf938e508fd10b01cb8d699c79083813takashistatic const char g_szWelcome[] = "VirtualBox-LiveMigration-1.0\n";
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen/**
af84459fbf938e508fd10b01cb8d699c79083813takashi * @copydoc FNRTTIMERLR
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowestatic DECLCALLBACK(void) migrationTimeout(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick)
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe{
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe /* This is harmless for any open connections. */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe RTTcpServerShutdown((PRTTCPSERVER)pvUser);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe}
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wroweSTDMETHODIMP
cd34a6fbf0a2619544a72eadb73f309370bf6682wroweConsole::Migrate(IN_BSTR aHostname, ULONG aPort, IN_BSTR aPassword, IProgress **aProgress)
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen{
78f97ce162b66a0dbfd7af4dcd9984f162569b04minfrin return E_FAIL;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe}
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe/**
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Creates a TCP server that listens for the source machine and passes control
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * over to Console::migrationServeConnection().
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe *
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * @returns VBox status code.
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen * @param pVM The VM handle
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen * @param pMachine The IMachine for the virtual machine.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wroweint
cd34a6fbf0a2619544a72eadb73f309370bf6682wroweConsole::migrationLoadRemote(PVM pVM, IMachine *pMachine)
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe{
4bebf996eb7002ebfe897d46a0e0572390604a77nd /*
4bebf996eb7002ebfe897d46a0e0572390604a77nd * Get the config.
4bebf996eb7002ebfe897d46a0e0572390604a77nd */
4bebf996eb7002ebfe897d46a0e0572390604a77nd ULONG uPort;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe HRESULT hrc = pMachine->COMGETTER(LiveMigrationPort)(&uPort);
4bebf996eb7002ebfe897d46a0e0572390604a77nd if (FAILED(hrc))
9534272616b71aaea50aeec4162e749a96aebd7fsf return VERR_GENERAL_FAILURE;
4bebf996eb7002ebfe897d46a0e0572390604a77nd
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe Bstr bstrPassword;
af84459fbf938e508fd10b01cb8d699c79083813takashi hrc = pMachine->COMGETTER(LiveMigrationPassword)(bstrPassword.asOutParam());
af84459fbf938e508fd10b01cb8d699c79083813takashi if (FAILED(hrc))
af84459fbf938e508fd10b01cb8d699c79083813takashi return VERR_GENERAL_FAILURE;
af84459fbf938e508fd10b01cb8d699c79083813takashi Utf8Str strPassword(bstrPassword);
af84459fbf938e508fd10b01cb8d699c79083813takashi strPassword.append('\n'); /* always ends with a newline. */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe Utf8Str strBind("");
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen /** @todo Add a bind address property. */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe const char *pszBindAddress = strBind.isEmpty() ? NULL : strBind.c_str();
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe /*
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Create the TCP server.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe int rc;
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen PRTTCPSERVER hServer;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe if (uPort)
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe rc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe else
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe for (int cTries = 10240; cTries > 0; cTries--)
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe uPort = RTRandU32Ex(cTries >= 8192 ? 49152 : 1024, 65534);
57c845e03570b3641fbf41d4f139e2a9b49e406and rc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer);
57c845e03570b3641fbf41d4f139e2a9b49e406and if (rc != VERR_NET_ADDRESS_IN_USE)
57c845e03570b3641fbf41d4f139e2a9b49e406and break;
57c845e03570b3641fbf41d4f139e2a9b49e406and }
57c845e03570b3641fbf41d4f139e2a9b49e406and if (RT_SUCCESS(rc))
57c845e03570b3641fbf41d4f139e2a9b49e406and {
4b311579b2c8aebac85fb7cb8ac89e6c37b4bc1asf HRESULT hrc = pMachine->COMSETTER(LiveMigrationPort)(uPort);
57c845e03570b3641fbf41d4f139e2a9b49e406and if (FAILED(hrc))
7e9d90004f580231e0376880710dc25408950ab9rbowen {
7e9d90004f580231e0376880710dc25408950ab9rbowen RTTcpServerDestroy(hServer);
7e9d90004f580231e0376880710dc25408950ab9rbowen return VERR_GENERAL_FAILURE;
7e9d90004f580231e0376880710dc25408950ab9rbowen }
7e9d90004f580231e0376880710dc25408950ab9rbowen }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe if (RT_FAILURE(rc))
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe return rc;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe /*
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen * Create a timer for timing out after 5 mins.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe RTTIMERLR hTimer;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe rc = RTTimerLRCreateEx(&hTimer, 0, 0, migrationTimeout, hServer);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe if (RT_SUCCESS(rc))
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe rc = RTTimerLRStart(hTimer, 5*60*UINT64_C(1000000000) /*ns*/);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe if (RT_SUCCESS(rc))
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe /*
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Do the job, when it returns we're done.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe MIGRATIONSERVEARGS Args;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe Args.pConsole = this;
4aa603e6448b99f9371397d439795c91a93637eand Args.pMachine = pMachine;
4aa603e6448b99f9371397d439795c91a93637eand Args.pVM = pVM;
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh Args.pszPassword = strPassword.c_str();
20f499565e77defe9dab24dd85c02f38a1175855nd Args.hTimer = hTimer;
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh rc = RTTcpServerListen(hServer, Console::migrationServeConnection, &Args);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
4aa603e6448b99f9371397d439795c91a93637eand RTTimerLRDestroy(hTimer);
4aa603e6448b99f9371397d439795c91a93637eand }
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh RTTcpServerDestroy(hServer);
20f499565e77defe9dab24dd85c02f38a1175855nd
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh return rc;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe}
f039cf01b271a31e317d5b84f24cb135f1c1b6d7nd
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe/**
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Reads a string from the socket.
4aa603e6448b99f9371397d439795c91a93637eand *
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh * @returns VBox status code.
4aa603e6448b99f9371397d439795c91a93637eand *
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh * @param Sock The socket.
20f499565e77defe9dab24dd85c02f38a1175855nd * @param pszBuf The output buffer.
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh * @param cchBuf The size of the output buffer.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe *
af84459fbf938e508fd10b01cb8d699c79083813takashi */
af84459fbf938e508fd10b01cb8d699c79083813takashistatic int migrationReadLine(RTSOCKET Sock, char *pszBuf, size_t cchBuf)
2d39a41e98476f5235b7c37ce745a4aa0904b1cbrbowen{
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen char *pszStart = pszBuf;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe AssertReturn(cchBuf > 1, VERR_INTERNAL_ERROR);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe /* dead simple (stupid) approach. */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe for (;;)
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe char ch;
c8c717fafa0a09ed13469a603a178921b851dd22igalic int rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL);
c8c717fafa0a09ed13469a603a178921b851dd22igalic if (RT_FAILURE(rc))
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic {
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic LogRel(("Migration: RTTcpRead -> %Rrc while reading string ('%s')\n", rc, pszStart));
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic return rc;
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic }
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic if ( ch == '\n'
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic || ch == '\0')
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic return VINF_SUCCESS;
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic if (cchBuf <= 1)
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic {
7c7e501f542451bf7225b23cb299ee4228bfe15dgryzor LogRel(("Migration: String buffer overflow: '%s'\n", pszStart));
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe return VERR_BUFFER_OVERFLOW;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe *pszBuf++ = ch;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe *pszBuf = '\0';
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe cchBuf--;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
acf65805923cf80834c39689cc0e2a8e7201c186sf}
acf65805923cf80834c39689cc0e2a8e7201c186sf
acf65805923cf80834c39689cc0e2a8e7201c186sf
c8c717fafa0a09ed13469a603a178921b851dd22igalic/**
7c7e501f542451bf7225b23cb299ee4228bfe15dgryzor * @copydoc FNRTTCPSERVE
4bebf996eb7002ebfe897d46a0e0572390604a77nd * VERR_TCP_SERVER_STOP
4bebf996eb7002ebfe897d46a0e0572390604a77nd */
4bebf996eb7002ebfe897d46a0e0572390604a77nd/*static*/ DECLCALLBACK(int)
8559a67073808d84d85bb5dd552d4247caafe709sfConsole::migrationServeConnection(RTSOCKET Sock, void *pvUser)
8559a67073808d84d85bb5dd552d4247caafe709sf{
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe PMIGRATIONSERVEARGS pArgs = (PMIGRATIONSERVEARGS)pvUser;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe Console *pConsole = pArgs->pConsole;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe IMachine *pMachine = pArgs->pMachine;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe PVM pVM = pArgs->pVM;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe const char *pszPassword = pArgs->pszPassword;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe /*
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Say hello.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe int rc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe if (RT_FAILURE(rc))
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe LogRel(("Migration: Failed to write welcome message: %Rrc\n", rc));
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe return VINF_SUCCESS;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
8559a67073808d84d85bb5dd552d4247caafe709sf /*
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen * Password (includes '\n', see migrationLoadRemote). If it's right, tell
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * the TCP server to stop listening (frees up host resources and makes sure
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * this is the last connection attempt).
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe unsigned off = 0;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe while (pszPassword[off])
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe char ch;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL);
253547fb9cc7986e84ff68aef076f664fc4169dctakashi if (RT_FAILURE(rc))
253547fb9cc7986e84ff68aef076f664fc4169dctakashi break;
253547fb9cc7986e84ff68aef076f664fc4169dctakashi if (pszPassword[off] != ch)
253547fb9cc7986e84ff68aef076f664fc4169dctakashi {
253547fb9cc7986e84ff68aef076f664fc4169dctakashi LogRel(("Migration: Invalid password (off=%u)\n", off));
253547fb9cc7986e84ff68aef076f664fc4169dctakashi return VINF_SUCCESS;
8559a67073808d84d85bb5dd552d4247caafe709sf }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe off++;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe RTTcpServerShutdown((PRTTCPSERVER)pvUser);
c8c717fafa0a09ed13469a603a178921b851dd22igalic
c8c717fafa0a09ed13469a603a178921b851dd22igalic /*
8559a67073808d84d85bb5dd552d4247caafe709sf * Command processing loop.
c8c717fafa0a09ed13469a603a178921b851dd22igalic */
c8c717fafa0a09ed13469a603a178921b851dd22igalic for (;;)
c8c717fafa0a09ed13469a603a178921b851dd22igalic {
8559a67073808d84d85bb5dd552d4247caafe709sf char szCmd[128];
8559a67073808d84d85bb5dd552d4247caafe709sf rc = migrationReadLine(Sock, szCmd, sizeof(szCmd));
8559a67073808d84d85bb5dd552d4247caafe709sf if (RT_FAILURE(rc))
8559a67073808d84d85bb5dd552d4247caafe709sf break;
8559a67073808d84d85bb5dd552d4247caafe709sf
8559a67073808d84d85bb5dd552d4247caafe709sf if (!strcmp(szCmd, "state"))
8559a67073808d84d85bb5dd552d4247caafe709sf {
8559a67073808d84d85bb5dd552d4247caafe709sf /* restore the state. */
8559a67073808d84d85bb5dd552d4247caafe709sf }
8559a67073808d84d85bb5dd552d4247caafe709sf else if (!strcmp(szCmd, "done"))
8559a67073808d84d85bb5dd552d4247caafe709sf break;
8559a67073808d84d85bb5dd552d4247caafe709sf else
8559a67073808d84d85bb5dd552d4247caafe709sf {
8559a67073808d84d85bb5dd552d4247caafe709sf LogRel(("Migration: Unknown command '%s'\n", szCmd));
8559a67073808d84d85bb5dd552d4247caafe709sf break;
8559a67073808d84d85bb5dd552d4247caafe709sf }
8559a67073808d84d85bb5dd552d4247caafe709sf }
8559a67073808d84d85bb5dd552d4247caafe709sf
8559a67073808d84d85bb5dd552d4247caafe709sf return VERR_TCP_SERVER_STOP;
8559a67073808d84d85bb5dd552d4247caafe709sf}
a55680cd56cecad4f2d7d41b576aa63f0e008916rjung
8559a67073808d84d85bb5dd552d4247caafe709sf