Changeset 31770 in vbox
- Timestamp:
- Aug 19, 2010 8:53:41 AM (14 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/FTM.cpp
r31766 r31770 35 35 #include <iprt/tcp.h> 36 36 37 /******************************************************************************* 38 * Global Variables * 39 *******************************************************************************/ 40 static const char g_szWelcome[] = "VirtualBox-Fault-Tolerance-Sync-1.0\n"; 41 37 42 /** 38 43 * Initializes the FTM. … … 44 49 { 45 50 /** @todo saved state for master nodes! */ 46 pVM->ftm.s.pszAddress = NULL; 47 pVM->ftm.s.pszPassword = NULL; 48 pVM->fFaultTolerantMaster = false; 49 pVM->ftm.s.fIsStandbyNode = false; 50 pVM->ftm.s.standby.hServer = NULL; 51 pVM->ftm.s.pszAddress = NULL; 52 pVM->ftm.s.pszPassword = NULL; 53 pVM->fFaultTolerantMaster = false; 54 pVM->ftm.s.fIsStandbyNode = false; 55 pVM->ftm.s.standby.hServer = NULL; 56 pVM->ftm.s.master.hShutdownEvent = NIL_RTSEMEVENT; 57 pVM->ftm.s.hSocket = NIL_RTSOCKET; 51 58 return VINF_SUCCESS; 52 59 } … … 56 63 * 57 64 * Termination means cleaning up and freeing all resources, 58 * the VM it 65 * the VM itself is at this point powered off or suspended. 59 66 * 60 67 * @returns VBox status code. … … 67 74 if (pVM->ftm.s.pszPassword) 68 75 RTMemFree(pVM->ftm.s.pszPassword); 76 if (pVM->ftm.s.hSocket != NIL_RTSOCKET) 77 RTTcpClientClose(pVM->ftm.s.hSocket); 69 78 if (pVM->ftm.s.standby.hServer) 70 79 RTTcpServerDestroy(pVM->ftm.s.standby.hServer); 80 if (pVM->ftm.s.master.hShutdownEvent != NIL_RTSEMEVENT) 81 RTSemEventDestroy(pVM->ftm.s.master.hShutdownEvent); 71 82 72 83 return VINF_SUCCESS; 84 } 85 86 87 static int ftmR3TcpWriteACK(PVM pVM) 88 { 89 int rc = RTTcpWrite(pVM->ftm.s.hSocket, "ACK\n", sizeof("ACK\n") - 1); 90 if (RT_FAILURE(rc)) 91 { 92 LogRel(("FTSync: RTTcpWrite(,ACK,) -> %Rrc\n", rc)); 93 } 94 return rc; 95 } 96 97 98 static int ftmR3TcpWriteNACK(PVM pVM, int32_t rc2, const char *pszMsgText = NULL) 99 { 100 char szMsg[256]; 101 size_t cch; 102 if (pszMsgText && *pszMsgText) 103 { 104 cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d;%s\n", rc2, pszMsgText); 105 for (size_t off = 6; off + 1 < cch; off++) 106 if (szMsg[off] == '\n') 107 szMsg[off] = '\r'; 108 } 109 else 110 cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d\n", rc2); 111 int rc = RTTcpWrite(pVM->ftm.s.hSocket, szMsg, cch); 112 if (RT_FAILURE(rc)) 113 LogRel(("FTSync: RTTcpWrite(,%s,%zu) -> %Rrc\n", szMsg, cch, rc)); 114 return rc; 115 } 116 117 /** 118 * Reads a string from the socket. 119 * 120 * @returns VBox status code. 121 * 122 * @param pState The teleporter state structure. 123 * @param pszBuf The output buffer. 124 * @param cchBuf The size of the output buffer. 125 * 126 */ 127 static int ftmR3TcpReadLine(PVM pVM, char *pszBuf, size_t cchBuf) 128 { 129 char *pszStart = pszBuf; 130 RTSOCKET Sock = pVM->ftm.s.hSocket; 131 132 AssertReturn(cchBuf > 1, VERR_INTERNAL_ERROR); 133 *pszBuf = '\0'; 134 135 /* dead simple approach. */ 136 for (;;) 137 { 138 char ch; 139 int rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 140 if (RT_FAILURE(rc)) 141 { 142 LogRel(("FTSync: RTTcpRead -> %Rrc while reading string ('%s')\n", rc, pszStart)); 143 return rc; 144 } 145 if ( ch == '\n' 146 || ch == '\0') 147 return VINF_SUCCESS; 148 if (cchBuf <= 1) 149 { 150 LogRel(("FTSync: String buffer overflow: '%s'\n", pszStart)); 151 return VERR_BUFFER_OVERFLOW; 152 } 153 *pszBuf++ = ch; 154 *pszBuf = '\0'; 155 cchBuf--; 156 } 157 } 158 159 /** 160 * Reads an ACK or NACK. 161 * 162 * @returns VBox status code. 163 * @param pVM The VM to operate on. 164 * @param pszWhich Which ACK is this this? 165 * @param pszNAckMsg Optional NACK message. 166 */ 167 static int ftmR3TcpReadACK(PVM pVM, const char *pszWhich, const char *pszNAckMsg /*= NULL*/) 168 { 169 char szMsg[256]; 170 int rc = ftmR3TcpReadLine(pVM, szMsg, sizeof(szMsg)); 171 if (RT_FAILURE(rc)) 172 return rc; 173 174 if (!strcmp(szMsg, "ACK")) 175 return VINF_SUCCESS; 176 177 if (!strncmp(szMsg, "NACK=", sizeof("NACK=") - 1)) 178 { 179 char *pszMsgText = strchr(szMsg, ';'); 180 if (pszMsgText) 181 *pszMsgText++ = '\0'; 182 183 int32_t vrc2; 184 rc = RTStrToInt32Full(&szMsg[sizeof("NACK=") - 1], 10, &vrc2); 185 if (rc == VINF_SUCCESS) 186 { 187 /* 188 * Well formed NACK, transform it into an error. 189 */ 190 if (pszNAckMsg) 191 { 192 LogRel(("FTSync: %s: NACK=%Rrc (%d)\n", pszWhich, vrc2, vrc2)); 193 return VERR_INTERNAL_ERROR; 194 } 195 196 if (pszMsgText) 197 { 198 pszMsgText = RTStrStrip(pszMsgText); 199 for (size_t off = 0; pszMsgText[off]; off++) 200 if (pszMsgText[off] == '\r') 201 pszMsgText[off] = '\n'; 202 203 LogRel(("FTSync: %s: NACK=%Rrc (%d) - '%s'\n", pszWhich, vrc2, vrc2, pszMsgText)); 204 } 205 return VERR_INTERNAL_ERROR_2; 206 } 207 208 if (pszMsgText) 209 pszMsgText[-1] = ';'; 210 } 211 return VERR_INTERNAL_ERROR_3; 73 212 } 74 213 … … 84 223 static DECLCALLBACK(int) ftmR3MasterThread(RTTHREAD Thread, void *pvUser) 85 224 { 86 return VINF_SUCCESS; 225 int rc = VINF_SUCCESS; 226 PVM pVM = (PVM)pvUser; 227 228 for (;;) 229 { 230 /* 231 * Try connect to the standby machine. 232 */ 233 rc = RTTcpClientConnect(pVM->ftm.s.pszAddress, pVM->ftm.s.uPort, &pVM->ftm.s.hSocket); 234 if (RT_SUCCESS(rc)) 235 { 236 /* Disable Nagle. */ 237 rc = RTTcpSetSendCoalescing(pVM->ftm.s.hSocket, false /*fEnable*/); 238 AssertRC(rc); 239 240 /* Read and check the welcome message. */ 241 char szLine[RT_MAX(128, sizeof(g_szWelcome))]; 242 RT_ZERO(szLine); 243 rc = RTTcpRead(pVM->ftm.s.hSocket, szLine, sizeof(g_szWelcome) - 1, NULL); 244 if ( RT_SUCCESS(rc) 245 && !strcmp(szLine, g_szWelcome)) 246 { 247 /* password */ 248 rc = RTTcpWrite(pVM->ftm.s.hSocket, pVM->ftm.s.pszPassword, strlen(pVM->ftm.s.pszPassword)); 249 if (RT_SUCCESS(rc)) 250 { 251 /* ACK */ 252 rc = ftmR3TcpReadACK(pVM, "password", "Invalid password"); 253 if (RT_SUCCESS(rc)) 254 break; 255 } 256 } 257 rc = RTTcpClientClose(pVM->ftm.s.hSocket); 258 AssertRC(rc); 259 pVM->ftm.s.hSocket = NIL_RTSOCKET; 260 } 261 rc = RTSemEventWait(pVM->ftm.s.master.hShutdownEvent, 1000 /* 1 second */); 262 if (rc != VERR_TIMEOUT) 263 return VINF_SUCCESS; /* told to quit */ 264 } 265 266 /* Successfully initialized the connection to the standby node. 267 * Start the sync process. 268 */ 269 270 return rc; 87 271 } 88 272 … … 97 281 { 98 282 PVM pVM = (PVM)pvUser; 283 284 pVM->ftm.s.hSocket = Sock; 99 285 100 286 /* … … 104 290 AssertRC(rc); 105 291 106 return VINF_SUCCESS; 292 /* Send the welcome message to the master node. */ 293 rc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1); 294 if (RT_FAILURE(rc)) 295 { 296 LogRel(("Teleporter: Failed to write welcome message: %Rrc\n", rc)); 297 return VINF_SUCCESS; 298 } 299 300 /* 301 * Password. 302 */ 303 const char *pszPassword = pVM->ftm.s.pszPassword; 304 unsigned off = 0; 305 while (pszPassword[off]) 306 { 307 char ch; 308 rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 309 if ( RT_FAILURE(rc) 310 || pszPassword[off] != ch) 311 { 312 if (RT_FAILURE(rc)) 313 LogRel(("FTSync: Password read failure (off=%u): %Rrc\n", off, rc)); 314 else 315 LogRel(("FTSync: Invalid password (off=%u)\n", off)); 316 ftmR3TcpWriteNACK(pVM, VERR_AUTHENTICATION_FAILURE); 317 return VINF_SUCCESS; 318 } 319 off++; 320 } 321 rc = ftmR3TcpWriteACK(pVM); 322 if (RT_FAILURE(rc)) 323 return VINF_SUCCESS; 324 325 /* 326 * Stop the server. 327 * 328 * Note! After this point we must return VERR_TCP_SERVER_STOP, while prior 329 * to it we must not return that value! 330 */ 331 RTTcpServerShutdown(pVM->ftm.s.standby.hServer); 332 333 /* 334 * Command processing loop. 335 */ 336 bool fDone = false; 337 for (;;) 338 { 339 char szCmd[128]; 340 rc = ftmR3TcpReadLine(pVM, szCmd, sizeof(szCmd)); 341 if (RT_FAILURE(rc)) 342 break; 343 344 if (!strcmp(szCmd, "mem-sync")) 345 { 346 } 347 else 348 if (!strcmp(szCmd, "heartbeat")) 349 { 350 } 351 else 352 if (!strcmp(szCmd, "checkpoint")) 353 { 354 } 355 if (RT_FAILURE(rc)) 356 break; 357 } 358 LogFlowFunc(("returns mRc=%Rrc\n", rc)); 359 return VERR_TCP_SERVER_STOP; 107 360 } 108 361 … … 140 393 if (fMaster) 141 394 { 142 rc = RTThreadCreate(NULL, ftmR3MasterThread, NULL, 395 rc = RTSemEventCreate(&pVM->ftm.s.master.hShutdownEvent); 396 if (RT_FAILURE(rc)) 397 return rc; 398 399 rc = RTThreadCreate(NULL, ftmR3MasterThread, pVM, 143 400 0, RTTHREADTYPE_IO /* higher than normal priority */, 0, "ftmR3MasterThread"); 144 401 if (RT_FAILURE(rc)) -
trunk/src/VBox/VMM/FTMInternal.h
r31754 r31770 23 23 #include <VBox/ftm.h> 24 24 #include <iprt/tcp.h> 25 25 #include <iprt/semaphore.h> 26 26 27 27 /** @defgroup grp_ftm_int Internals. … … 49 49 bool fIsStandbyNode; 50 50 51 /** Current active socket. */ 52 RTSOCKET hSocket; 53 51 54 struct 52 55 { 53 56 PRTTCPSERVER hServer; 54 57 } standby; 58 59 struct 60 { 61 RTSEMEVENT hShutdownEvent; 62 } master; 55 63 56 64 } FTM;
Note:
See TracChangeset
for help on using the changeset viewer.