Changeset 23626 in vbox for trunk/src/VBox/Main
- Timestamp:
- Oct 8, 2009 4:56:52 PM (15 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp
r23606 r23626 26 26 #include "Logging.h" 27 27 28 #include <iprt/err.h> 29 #include <iprt/rand.h> 30 #include <iprt/tcp.h> 31 #include <iprt/timer.h> 32 28 33 #include <VBox/vmapi.h> 29 34 #include <VBox/ssm.h> … … 33 38 34 39 40 41 /******************************************************************************* 42 * Structures and Typedefs * 43 *******************************************************************************/ 44 /** 45 * Argument package for Console::migrationServeConnection. 46 */ 47 typedef struct MIGRATIONSERVEARGS 48 { 49 Console *pConsole; 50 IMachine *pMachine; 51 PVM pVM; 52 const char *pszPassword; 53 RTTIMERLR hTimer; 54 } MIGRATIONSERVEARGS; 55 typedef MIGRATIONSERVEARGS *PMIGRATIONSERVEARGS; 56 57 58 /******************************************************************************* 59 * Global Variables * 60 *******************************************************************************/ 61 static const char g_szWelcome[] = "VirtualBox-LiveMigration-1.0\n"; 62 63 64 65 /** 66 * @copydoc FNRTTIMERLR 67 */ 68 static DECLCALLBACK(void) migrationTimeout(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick) 69 { 70 /* This is harmless for any open connections. */ 71 RTTcpServerShutdown((PRTTCPSERVER)pvUser); 72 } 73 74 35 75 STDMETHODIMP 36 76 Console::Migrate(IN_BSTR aHostname, ULONG aPort, IN_BSTR aPassword, IProgress **aProgress) … … 39 79 } 40 80 81 82 /** 83 * Creates a TCP server that listens for the source machine and passes control 84 * over to Console::migrationServeConnection(). 85 * 86 * @returns VBox status code. 87 * @param pVM The VM handle 88 * @param pMachine The IMachine for the virtual machine. 89 */ 41 90 int 42 91 Console::migrationLoadRemote(PVM pVM, IMachine *pMachine) … … 55 104 return VERR_GENERAL_FAILURE; 56 105 Utf8Str strPassword(bstrPassword); 106 strPassword.append('\n'); /* always ends with a newline. */ 107 108 Utf8Str strBind(""); 109 /** @todo Add a bind address property. */ 110 const char *pszBindAddress = strBind.isEmpty() ? NULL : strBind.c_str(); 57 111 58 112 /* 59 113 * Create the TCP server. 60 114 */ 61 //RTTcpServerCreateEx(NULL, 62 63 64 return VERR_NOT_IMPLEMENTED; 65 } 66 115 int rc; 116 PRTTCPSERVER hServer; 117 if (uPort) 118 rc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer); 119 else 120 { 121 for (int cTries = 10240; cTries > 0; cTries--) 122 { 123 uPort = RTRandU32Ex(cTries >= 8192 ? 49152 : 1024, 65534); 124 rc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer); 125 if (rc != VERR_NET_ADDRESS_IN_USE) 126 break; 127 } 128 if (RT_SUCCESS(rc)) 129 { 130 HRESULT hrc = pMachine->COMSETTER(LiveMigrationPort)(uPort); 131 if (FAILED(hrc)) 132 { 133 RTTcpServerDestroy(hServer); 134 return VERR_GENERAL_FAILURE; 135 } 136 } 137 } 138 if (RT_FAILURE(rc)) 139 return rc; 140 141 /* 142 * Create a timer for timing out after 5 mins. 143 */ 144 RTTIMERLR hTimer; 145 rc = RTTimerLRCreateEx(&hTimer, 0, 0, migrationTimeout, hServer); 146 if (RT_SUCCESS(rc)) 147 { 148 rc = RTTimerLRStart(hTimer, 5*60*UINT64_C(1000000000) /*ns*/); 149 if (RT_SUCCESS(rc)) 150 { 151 /* 152 * Do the job, when it returns we're done. 153 */ 154 MIGRATIONSERVEARGS Args; 155 Args.pConsole = this; 156 Args.pMachine = pMachine; 157 Args.pVM = pVM; 158 Args.pszPassword = strPassword.c_str(); 159 Args.hTimer = hTimer; 160 rc = RTTcpServerListen(hServer, Console::migrationServeConnection, &Args); 161 } 162 163 RTTimerLRDestroy(hTimer); 164 } 165 RTTcpServerDestroy(hServer); 166 167 return rc; 168 } 169 170 /** 171 * Reads a string from the socket. 172 * 173 * @returns VBox status code. 174 * 175 * @param Sock The socket. 176 * @param pszBuf The output buffer. 177 * @param cchBuf The size of the output buffer. 178 * 179 */ 180 static int migrationReadLine(RTSOCKET Sock, char *pszBuf, size_t cchBuf) 181 { 182 char *pszStart = pszBuf; 183 AssertReturn(cchBuf > 1, VERR_INTERNAL_ERROR); 184 185 /* dead simple (stupid) approach. */ 186 for (;;) 187 { 188 char ch; 189 int rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 190 if (RT_FAILURE(rc)) 191 { 192 LogRel(("Migration: RTTcpRead -> %Rrc while reading string ('%s')\n", rc, pszStart)); 193 return rc; 194 } 195 if ( ch == '\n' 196 || ch == '\0') 197 return VINF_SUCCESS; 198 if (cchBuf <= 1) 199 { 200 LogRel(("Migration: String buffer overflow: '%s'\n", pszStart)); 201 return VERR_BUFFER_OVERFLOW; 202 } 203 *pszBuf++ = ch; 204 *pszBuf = '\0'; 205 cchBuf--; 206 } 207 } 208 209 210 /** 211 * @copydoc FNRTTCPSERVE 212 * VERR_TCP_SERVER_STOP 213 */ 214 /*static*/ DECLCALLBACK(int) 215 Console::migrationServeConnection(RTSOCKET Sock, void *pvUser) 216 { 217 PMIGRATIONSERVEARGS pArgs = (PMIGRATIONSERVEARGS)pvUser; 218 Console *pConsole = pArgs->pConsole; 219 IMachine *pMachine = pArgs->pMachine; 220 PVM pVM = pArgs->pVM; 221 const char *pszPassword = pArgs->pszPassword; 222 223 /* 224 * Say hello. 225 */ 226 int rc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1); 227 if (RT_FAILURE(rc)) 228 { 229 LogRel(("Migration: Failed to write welcome message: %Rrc\n", rc)); 230 return VINF_SUCCESS; 231 } 232 233 /* 234 * Password (includes '\n', see migrationLoadRemote). If it's right, tell 235 * the TCP server to stop listening (frees up host resources and makes sure 236 * this is the last connection attempt). 237 */ 238 unsigned off = 0; 239 while (pszPassword[off]) 240 { 241 char ch; 242 rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 243 if (RT_FAILURE(rc)) 244 break; 245 if (pszPassword[off] != ch) 246 { 247 LogRel(("Migration: Invalid password (off=%u)\n", off)); 248 return VINF_SUCCESS; 249 } 250 off++; 251 } 252 253 RTTcpServerShutdown((PRTTCPSERVER)pvUser); 254 255 /* 256 * Command processing loop. 257 */ 258 for (;;) 259 { 260 char szCmd[128]; 261 rc = migrationReadLine(Sock, szCmd, sizeof(szCmd)); 262 if (RT_FAILURE(rc)) 263 break; 264 265 if (!strcmp(szCmd, "state")) 266 { 267 /* restore the state. */ 268 } 269 else if (!strcmp(szCmd, "done")) 270 break; 271 else 272 { 273 LogRel(("Migration: Unknown command '%s'\n", szCmd)); 274 break; 275 } 276 } 277 278 return VERR_TCP_SERVER_STOP; 279 } 280 -
trunk/src/VBox/Main/include/ConsoleImpl.h
r23606 r23626 514 514 /** @name Live migration support 515 515 * @{ */ 516 int migrationLoadRemote(PVM pVM, IMachine *pMachine); 516 int migrationLoadRemote(PVM pVM, IMachine *pMachine); 517 static DECLCALLBACK(int) migrationServeConnection(RTSOCKET Sock, void *pvUser); 517 518 /** @} */ 518 519
Note:
See TracChangeset
for help on using the changeset viewer.