Changeset 89962 in vbox
- Timestamp:
- Jun 30, 2021 7:02:07 AM (4 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioTestService.cpp
r89803 r89962 20 20 * Header Files * 21 21 *********************************************************************************************************************************/ 22 #define LOG_GROUP RTLOGGROUP_DEFAULT 22 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO /** @todo Add an own log group for this? */ 23 23 24 #include <iprt/alloca.h> 24 25 #include <iprt/asm.h> … … 30 31 #include <iprt/env.h> 31 32 #include <iprt/err.h> 33 #include <iprt/file.h> 32 34 #include <iprt/getopt.h> 33 35 #include <iprt/handle.h> … … 47 49 #include <iprt/thread.h> 48 50 51 #include <VBox/log.h> 52 49 53 #include "AudioTestService.h" 50 54 #include "AudioTestServiceInternal.h" … … 54 58 * Structures and Typedefs * 55 59 *********************************************************************************************************************************/ 60 /** 61 * A generic ATS reply, used by the client 62 * to process the incoming packets. 63 */ 64 typedef struct ATSSRVREPLY 65 { 66 char szOp[ATSPKT_OPCODE_MAX_LEN]; 67 void *pvPayload; 68 size_t cbPayload; 69 } ATSSRVREPLY; 70 /** Pointer to a generic ATS reply. */ 71 typedef struct ATSSRVREPLY *PATSSRVREPLY; 56 72 57 73 … … 62 78 * Transport layers. 63 79 */ 64 staticconst PCATSTRANSPORT g_apTransports[] =80 const PCATSTRANSPORT g_apTransports[] = 65 81 { 66 82 &g_TcpTransport 67 83 }; 84 /** Number of transport layers in \a g_apTransports. */ 85 const size_t g_cTransports = RT_ELEMENTS(g_apTransports); 68 86 69 87 /** … … 99 117 } ATSCLIENTINST; 100 118 /** Pointer to a ATS client instance. */ 101 typedef ATSCLIENTINST *PATS CLIENTINST;119 typedef ATSCLIENTINST *PATSSERVERINST; 102 120 103 121 /** … … 130 148 * @returns IPRT status code. 131 149 * @param pThis The ATS instance. 132 * @param p ClientThe ATS client structure.150 * @param pInst The ATS client structure. 133 151 * @param pPkt The packet to send. Must point to a correctly 134 152 * aligned buffer. 135 153 */ 136 static int atsSendPkt(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPkt)154 static int atsSendPkt(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPkt) 137 155 { 138 156 Assert(pPkt->cb >= sizeof(*pPkt)); … … 142 160 143 161 LogFlowFunc(("cb=%RU32 (%#x), payload=%RU32 (%#x), opcode=%.8s\n", 144 pPkt->cb, pPkt->cb, pPkt->cb - sizeof(ATSPKTHDR), pPkt->cb - sizeof(ATSPKTHDR), pPkt->achOpcode)); 145 LogFlowFunc(("%.*Rhxd\n", RT_MIN(pPkt->cb, 256), pPkt)); 146 int rc = pThis->pTransport->pfnSendPkt(&pThis->TransportInst, pClient->pTransportClient, pPkt); 162 pPkt->cb, pPkt->cb, pPkt->cb - sizeof(ATSPKTHDR), pPkt->cb - sizeof(ATSPKTHDR), pPkt->achOpcode)); 163 int rc = pThis->pTransport->pfnSendPkt(pThis->pTransportInst, pInst->pTransportClient, pPkt); 147 164 while (RT_UNLIKELY(rc == VERR_INTERRUPTED) && !pThis->fTerminate) 148 rc = pThis->pTransport->pfnSendPkt( &pThis->TransportInst, pClient->pTransportClient, pPkt);165 rc = pThis->pTransport->pfnSendPkt(pThis->pTransportInst, pInst->pTransportClient, pPkt); 149 166 150 167 return rc; … … 155 172 * 156 173 * @param pThis The ATS instance. 157 * @param p Client The ATS client structure.174 * @param pInst The ATS server instance. 158 175 * @param pszOpcode The BABBLE opcode. 159 176 */ 160 static void atsReplyBabble(PATSSERVER pThis, PATS CLIENTINST pClient, const char *pszOpcode)177 static void atsReplyBabble(PATSSERVER pThis, PATSSERVERINST pInst, const char *pszOpcode) 161 178 { 162 179 ATSPKTHDR Reply; … … 165 182 memcpy(Reply.achOpcode, pszOpcode, sizeof(Reply.achOpcode)); 166 183 167 pThis->pTransport->pfnBabble( &pThis->TransportInst, pClient->pTransportClient, &Reply, 20*1000);184 pThis->pTransport->pfnBabble(pThis->pTransportInst, pInst->pTransportClient, &Reply, 20*1000); 168 185 } 169 186 … … 176 193 * @returns IPRT status code. 177 194 * @param pThis The ATS instance. 178 * @param p Client The ATS clientstructure.195 * @param pInst The opaque ATS instance structure. 179 196 * @param ppPktHdr Where to return the packet on success. Free 180 197 * with RTMemFree. 181 198 * @param fAutoRetryOnFailure Whether to retry on error. 182 199 */ 183 static int atsRecvPkt(PATSSERVER pThis, PATS CLIENTINST pClient, PPATSPKTHDR ppPktHdr, bool fAutoRetryOnFailure)200 static int atsRecvPkt(PATSSERVER pThis, PATSSERVERINST pInst, PPATSPKTHDR ppPktHdr, bool fAutoRetryOnFailure) 184 201 { 185 202 for (;;) 186 203 { 187 204 PATSPKTHDR pPktHdr; 188 int rc = pThis->pTransport->pfnRecvPkt( &pThis->TransportInst, pClient->pTransportClient, &pPktHdr);205 int rc = pThis->pTransport->pfnRecvPkt(pThis->pTransportInst, pInst->pTransportClient, &pPktHdr); 189 206 if (RT_SUCCESS(rc)) 190 207 { … … 193 210 && pPktHdr->cb < ATSPKT_MAX_SIZE) 194 211 { 195 Log2(("atsRecvPkt: pPktHdr=%p cb=%#x crc32=%#x opcode=%.8s\n" 196 "%.*Rhxd\n", 197 pPktHdr, pPktHdr->cb, pPktHdr->uCrc32, pPktHdr->achOpcode, RT_MIN(pPktHdr->cb, 256), pPktHdr)); 212 Log2Func(("pPktHdr=%p cb=%#x crc32=%#x opcode=%.8s\n", 213 pPktHdr, pPktHdr->cb, pPktHdr->uCrc32, pPktHdr->achOpcode)); 198 214 uint32_t uCrc32Calc = pPktHdr->uCrc32 != 0 199 215 ? RTCrc32(&pPktHdr->achOpcode[0], pPktHdr->cb - RT_UOFFSETOF(ATSPKTHDR, achOpcode)) … … 212 228 ) 213 229 { 214 Log((" atsRecvPkt:cb=%#x opcode=%.8s\n", pPktHdr->cb, pPktHdr->achOpcode));230 Log(("cb=%#x opcode=%.8s\n", pPktHdr->cb, pPktHdr->achOpcode)); 215 231 *ppPktHdr = pPktHdr; 216 232 return rc; … … 221 237 else 222 238 { 223 Log((" atsRecvPkt:cb=%#x opcode=%.8s crc32=%#x actual=%#x\n",239 Log(("cb=%#x opcode=%.8s crc32=%#x actual=%#x\n", 224 240 pPktHdr->cb, pPktHdr->achOpcode, pPktHdr->uCrc32, uCrc32Calc)); 225 241 rc = VERR_IO_CRC; … … 232 248 connection oriented. */ 233 249 if (rc == VERR_IO_BAD_LENGTH) 234 atsReplyBabble(pThis, p Client, "BABBLE L");250 atsReplyBabble(pThis, pInst, "BABBLE L"); 235 251 else if (rc == VERR_IO_CRC) 236 atsReplyBabble(pThis, p Client, "BABBLE C");252 atsReplyBabble(pThis, pInst, "BABBLE C"); 237 253 else if (rc == VERR_IO_BAD_COMMAND) 238 atsReplyBabble(pThis, p Client, "BABBLE O");254 atsReplyBabble(pThis, pInst, "BABBLE O"); 239 255 else 240 atsReplyBabble(pThis, p Client, "BABBLE ");256 atsReplyBabble(pThis, pInst, "BABBLE "); 241 257 RTMemFree(pPktHdr); 242 258 } … … 248 264 ) 249 265 { 250 Log((" atsRecvPkt:rc=%Rrc\n", rc));266 Log(("rc=%Rrc\n", rc)); 251 267 return rc; 252 268 } … … 259 275 * @returns IPRT status code of the send. 260 276 * @param pThis The ATS instance. 261 * @param p Client The ATS clientstructure.277 * @param pInst The opaque ATS instance structure. 262 278 * @param pReply The reply packet. 263 279 * @param pszOpcode The status opcode. Exactly 8 chars long, padd … … 265 281 * @param cbExtra Bytes in addition to the header. 266 282 */ 267 static int atsReplyInternal(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pReply, const char *pszOpcode, size_t cbExtra)283 static int atsReplyInternal(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pReply, const char *pszOpcode, size_t cbExtra) 268 284 { 269 285 /* copy the opcode, don't be too strict in case of a padding screw up. */ … … 284 300 pReply->uCrc32 = 0; 285 301 286 return atsSendPkt(pThis, p Client, pReply);302 return atsSendPkt(pThis, pInst, pReply); 287 303 } 288 304 … … 292 308 * @returns IPRT status code of the send. 293 309 * @param pThis The ATS instance. 294 * @param p Client The ATS clientstructure.310 * @param pInst The opaque ATS instance structure. 295 311 * @param pPktHdr The original packet (for future use). 296 312 * @param pszOpcode The status opcode. Exactly 8 chars long, padd 297 313 * with space. 298 314 */ 299 static int atsReplySimple(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr, const char *pszOpcode)300 { 301 return atsReplyInternal(pThis, p Client, pPktHdr, pszOpcode, 0);315 static int atsReplySimple(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr, const char *pszOpcode) 316 { 317 return atsReplyInternal(pThis, pInst, pPktHdr, pszOpcode, 0); 302 318 } 303 319 … … 307 323 * @returns IPRT status code of the send. 308 324 * @param pThis The ATS instance. 309 * @param p Client The ATS clientstructure.325 * @param pInst The opaque ATS instance structure. 310 326 * @param pPktHdr The original packet (for future use). 311 327 */ 312 static int atsReplyAck(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)313 { 314 return atsReplySimple(pThis, p Client, pPktHdr, "ACK ");328 static int atsReplyAck(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 329 { 330 return atsReplySimple(pThis, pInst, pPktHdr, "ACK "); 315 331 } 316 332 … … 320 336 * @returns IPRT status code of the send. 321 337 * @param pThis The ATS instance. 322 * @param p Client The ATS clientstructure.338 * @param pInst The opaque ATS instance structure. 323 339 * @param pPktHdr The original packet (for future use). 324 340 * @param pszOpcode The status opcode. Exactly 8 chars long, padd … … 328 344 * @param va Format arguments. 329 345 */ 330 static int atsReplyFailureV(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr,346 static int atsReplyFailureV(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr, 331 347 const char *pszOpcode, int rcReq, const char *pszDetailFmt, va_list va) 332 348 { … … 346 362 uPkt.rc = rcReq; 347 363 348 return atsReplyInternal(pThis, p Client, &uPkt.Hdr, pszOpcode, sizeof(int) + cchDetail + 1);364 return atsReplyInternal(pThis, pInst, &uPkt.Hdr, pszOpcode, sizeof(int) + cchDetail + 1); 349 365 } 350 366 … … 354 370 * @returns IPRT status code of the send. 355 371 * @param pThis The ATS instance. 356 * @param p Client The ATS clientstructure.372 * @param pInst The opaque ATS instance structure. 357 373 * @param pPktHdr The original packet (for future use). 358 374 * @param pszOpcode The status opcode. Exactly 8 chars long, padd … … 362 378 * @param ... Format arguments. 363 379 */ 364 static int atsReplyFailure(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr,380 static int atsReplyFailure(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr, 365 381 const char *pszOpcode, int rcReq, const char *pszDetailFmt, ...) 366 382 { 367 383 va_list va; 368 384 va_start(va, pszDetailFmt); 369 int rc = atsReplyFailureV(pThis, p Client, pPktHdr, pszOpcode, rcReq, pszDetailFmt, va);385 int rc = atsReplyFailureV(pThis, pInst, pPktHdr, pszOpcode, rcReq, pszDetailFmt, va); 370 386 va_end(va); 371 387 return rc; … … 377 393 * @returns IPRT status code of the send. 378 394 * @param pThis The ATS instance. 379 * @param p Client The ATS clientstructure.395 * @param pInst The opaque ATS instance structure. 380 396 * @param pPktHdr The packet to reply to. 381 397 * @param rcOperation The status code to report. … … 385 401 */ 386 402 static int atsReplyRC(PATSSERVER pThis, 387 PATS CLIENTINST pClient, PATSPKTHDR pPktHdr, int rcOperation, const char *pszOperationFmt, ...)403 PATSSERVERINST pInst, PATSPKTHDR pPktHdr, int rcOperation, const char *pszOperationFmt, ...) 388 404 { 389 405 if (RT_SUCCESS(rcOperation)) 390 return atsReplyAck(pThis, p Client, pPktHdr);406 return atsReplyAck(pThis, pInst, pPktHdr); 391 407 392 408 char szOperation[128]; … … 396 412 va_end(va); 397 413 398 return atsReplyFailure(pThis, p Client, pPktHdr, "FAILED ", rcOperation, "%s failed with rc=%Rrc (opcode '%.8s')",414 return atsReplyFailure(pThis, pInst, pPktHdr, "FAILED ", rcOperation, "%s failed with rc=%Rrc (opcode '%.8s')", 399 415 szOperation, rcOperation, pPktHdr->achOpcode); 400 416 } … … 405 421 * @returns IPRT status code of the send. 406 422 * @param pThis The ATS instance. 407 * @param p Client The ATS clientstructure.423 * @param pInst The opaque ATS instance structure. 408 424 * @param pPktHdr The packet to reply to. 409 425 * @param cb The wanted size. 410 426 */ 411 static int atsReplyBadSize(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr, size_t cb)412 { 413 return atsReplyFailure(pThis, p Client, pPktHdr, "BAD SIZE", VERR_INVALID_PARAMETER, "Expected at %zu bytes, got %u (opcode '%.8s')",427 static int atsReplyBadSize(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr, size_t cb) 428 { 429 return atsReplyFailure(pThis, pInst, pPktHdr, "BAD SIZE", VERR_INVALID_PARAMETER, "Expected at %zu bytes, got %u (opcode '%.8s')", 414 430 cb, pPktHdr->cb, pPktHdr->achOpcode); 415 431 } … … 420 436 * @returns IPRT status code of the send. 421 437 * @param pThis The ATS instance. 422 * @param p Client The ATS clientstructure.438 * @param pInst The opaque ATS instance structure. 423 439 * @param pPktHdr The packet to reply to. 424 440 */ 425 static int atsReplyUnknown(PATSSERVER pThis, PATSCLIENTINST pClient, PATSPKTHDR pPktHdr) 426 { 427 return atsReplyFailure(pThis, pClient, pPktHdr, "UNKNOWN ", VERR_NOT_FOUND, "Opcode '%.8s' is not known", pPktHdr->achOpcode); 428 } 429 430 #if 0 431 /** 432 * Deals with a command which contains an unterminated string. 441 static int atsReplyUnknown(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 442 { 443 return atsReplyFailure(pThis, pInst, pPktHdr, "UNKNOWN ", VERR_NOT_FOUND, "Opcode '%.8s' is not known", pPktHdr->achOpcode); 444 } 445 446 /** 447 * Deals with a command sent in an invalid client state. 433 448 * 434 449 * @returns IPRT status code of the send. 435 * @param pClient The ATS client structure. 450 * @param pThis The ATS instance. 451 * @param pInst The opaque ATS instance structure. 436 452 * @param pPktHdr The packet containing the unterminated string. 437 453 */ 438 static int atsReplyBadStrTermination(PATSCLIENT pClient, PATSPKTHDR pPktHdr) 439 { 440 return atsReplyFailure(pClient, pPktHdr, "BAD TERM", VERR_INVALID_PARAMETER, "Opcode '%.8s' contains an unterminated string", pPktHdr->achOpcode); 441 } 442 #endif 443 444 /** 445 * Deals with a command sent in an invalid client state. 446 * 447 * @returns IPRT status code of the send. 448 * @param pThis The ATS instance. 449 * @param pClient The ATS client structure. 450 * @param pPktHdr The packet containing the unterminated string. 451 */ 452 static int atsReplyInvalidState(PATSSERVER pThis, PATSCLIENTINST pClient, PATSPKTHDR pPktHdr) 453 { 454 return atsReplyFailure(pThis, pClient, pPktHdr, "INVSTATE", VERR_INVALID_STATE, "Opcode '%.8s' is not supported at client state '%s", 455 pPktHdr->achOpcode, atsClientStateStringify(pClient->enmState)); 454 static int atsReplyInvalidState(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 455 { 456 return atsReplyFailure(pThis, pInst, pPktHdr, "INVSTATE", VERR_INVALID_STATE, "Opcode '%.8s' is not supported at client state '%s", 457 pPktHdr->achOpcode, atsClientStateStringify(pInst->enmState)); 456 458 } 457 459 … … 461 463 * @returns IPRT status code. 462 464 * @param pThis The ATS instance. 463 * @param p Client The ATS clientstructure.465 * @param pInst The opaque ATS instance structure. 464 466 * @param pPktHdr The bye packet. 465 467 */ 466 static int atsDoBye(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)468 static int atsDoBye(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 467 469 { 468 470 int rc; 469 471 if (pPktHdr->cb == sizeof(ATSPKTHDR)) 470 472 { 471 rc = atsReplyAck(pThis, p Client, pPktHdr);473 rc = atsReplyAck(pThis, pInst, pPktHdr); 472 474 } 473 475 else 474 rc = atsReplyBadSize(pThis, p Client, pPktHdr, sizeof(ATSPKTHDR));476 rc = atsReplyBadSize(pThis, pInst, pPktHdr, sizeof(ATSPKTHDR)); 475 477 return rc; 476 478 } … … 481 483 * @returns IPRT status code. 482 484 * @param pThis The ATS instance. 483 * @param p Client The ATS clientstructure.485 * @param pInst The opaque ATS instance structure. 484 486 * @param pPktHdr The howdy packet. 485 487 */ 486 static int atsDoHowdy(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)488 static int atsDoHowdy(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 487 489 { 488 490 int rc = VINF_SUCCESS; 489 491 490 492 if (pPktHdr->cb != sizeof(ATSPKTREQHOWDY)) 491 return atsReplyBadSize(pThis, p Client, pPktHdr, sizeof(ATSPKTREQHOWDY));492 493 if (p Client->enmState != ATSCLIENTSTATE_INITIALISING)494 return atsReplyInvalidState(pThis, p Client, pPktHdr);493 return atsReplyBadSize(pThis, pInst, pPktHdr, sizeof(ATSPKTREQHOWDY)); 494 495 if (pInst->enmState != ATSCLIENTSTATE_INITIALISING) 496 return atsReplyInvalidState(pThis, pInst, pPktHdr); 495 497 496 498 PATSPKTREQHOWDY pReq = (PATSPKTREQHOWDY)pPktHdr; 497 499 498 500 if (pReq->uVersion != ATS_PROTOCOL_VS) 499 return atsReplyRC(pThis, p Client, pPktHdr, VERR_VERSION_MISMATCH, "The given version %#x is not supported", pReq->uVersion);501 return atsReplyRC(pThis, pInst, pPktHdr, VERR_VERSION_MISMATCH, "The given version %#x is not supported", pReq->uVersion); 500 502 501 503 ATSPKTREPHOWDY Rep; … … 504 506 Rep.uVersion = ATS_PROTOCOL_VS; 505 507 506 rc = atsReplyInternal(pThis, p Client, &Rep.Hdr, "ACK ", sizeof(Rep) - sizeof(ATSPKTHDR));508 rc = atsReplyInternal(pThis, pInst, &Rep.Hdr, "ACK ", sizeof(Rep) - sizeof(ATSPKTHDR)); 507 509 if (RT_SUCCESS(rc)) 508 510 { 509 pThis->pTransport->pfnNotifyHowdy( &pThis->TransportInst, pClient->pTransportClient);510 p Client->enmState = ATSCLIENTSTATE_READY;511 pThis->pTransport->pfnNotifyHowdy(pThis->pTransportInst, pInst->pTransportClient); 512 pInst->enmState = ATSCLIENTSTATE_READY; 511 513 } 512 514 … … 519 521 * @returns IPRT status code. 520 522 * @param pThis The ATS instance. 521 * @param p Client The ATS clientstructure.523 * @param pInst The opaque ATS instance structure. 522 524 * @param pPktHdr The test set begin packet. 523 525 */ 524 static int atsDoTestSetBegin(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)526 static int atsDoTestSetBegin(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 525 527 { 526 528 if (pPktHdr->cb != sizeof(ATSPKTREQTSETBEG)) 527 return atsReplyBadSize(pThis, p Client, pPktHdr, sizeof(ATSPKTREQTSETBEG));529 return atsReplyBadSize(pThis, pInst, pPktHdr, sizeof(ATSPKTREQTSETBEG)); 528 530 529 531 PATSPKTREQTSETBEG pReq = (PATSPKTREQTSETBEG)pPktHdr; … … 535 537 rc = pThis->Callbacks.pfnTestSetBegin(pThis->Callbacks.pvUser, pReq->szTag); 536 538 if (RT_FAILURE(rc)) 537 return atsReplyRC(pThis, p Client, pPktHdr, rc, "Beginning test set '%s' failed", pReq->szTag);539 return atsReplyRC(pThis, pInst, pPktHdr, rc, "Beginning test set '%s' failed", pReq->szTag); 538 540 } 539 541 540 542 if (RT_SUCCESS(rc)) 541 543 { 542 rc = atsReplyAck(pThis, p Client, pPktHdr);544 rc = atsReplyAck(pThis, pInst, pPktHdr); 543 545 } 544 546 else 545 rc = atsReplyRC(pThis, p Client, pPktHdr, rc, "Beginning test set failed");547 rc = atsReplyRC(pThis, pInst, pPktHdr, rc, "Beginning test set failed"); 546 548 547 549 return rc; … … 553 555 * @returns IPRT status code. 554 556 * @param pThis The ATS instance. 555 * @param p Client The ATS clientstructure.557 * @param pInst The opaque ATS instance structure. 556 558 * @param pPktHdr The test set end packet. 557 559 */ 558 static int atsDoTestSetEnd(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)560 static int atsDoTestSetEnd(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 559 561 { 560 562 if (pPktHdr->cb != sizeof(ATSPKTREQTSETEND)) 561 return atsReplyBadSize(pThis, p Client, pPktHdr, sizeof(ATSPKTREQTSETEND));563 return atsReplyBadSize(pThis, pInst, pPktHdr, sizeof(ATSPKTREQTSETEND)); 562 564 563 565 PATSPKTREQTSETEND pReq = (PATSPKTREQTSETEND)pPktHdr; … … 569 571 rc = pThis->Callbacks.pfnTestSetEnd(pThis->Callbacks.pvUser, pReq->szTag); 570 572 if (RT_FAILURE(rc)) 571 return atsReplyRC(pThis, p Client, pPktHdr, rc, "Ending test set '%s' failed", pReq->szTag);573 return atsReplyRC(pThis, pInst, pPktHdr, rc, "Ending test set '%s' failed", pReq->szTag); 572 574 } 573 575 if (RT_SUCCESS(rc)) 574 576 { 575 rc = atsReplyAck(pThis, p Client, pPktHdr);577 rc = atsReplyAck(pThis, pInst, pPktHdr); 576 578 } 577 579 else 578 rc = atsReplyRC(pThis, p Client, pPktHdr, rc, "Ending test set failed");580 rc = atsReplyRC(pThis, pInst, pPktHdr, rc, "Ending test set failed"); 579 581 580 582 return rc; … … 588 590 * or whatever atsRecvPkt returns. 589 591 * @param pThis The ATS instance. 590 * @param p Client The ATS clientstructure.592 * @param pInst The opaque ATS instance structure. 591 593 * @param pPktHdr The original packet (for future use). 592 594 */ 593 static int atsWaitForAck(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)595 static int atsWaitForAck(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 594 596 { 595 597 RT_NOREF(pPktHdr); 596 598 /** @todo timeout? */ 597 599 PATSPKTHDR pReply; 598 int rc = atsRecvPkt(pThis, p Client, &pReply, false /*fAutoRetryOnFailure*/);600 int rc = atsRecvPkt(pThis, pInst, &pReply, false /*fAutoRetryOnFailure*/); 599 601 if (RT_SUCCESS(rc)) 600 602 { … … 605 607 else 606 608 { 607 atsReplyBabble(pThis, p Client, "BABBLE ");609 atsReplyBabble(pThis, pInst, "BABBLE "); 608 610 rc = VERR_NET_NOT_CONNECTED; 609 611 } … … 618 620 * @returns IPRT status code. 619 621 * @param pThis The ATS instance. 620 * @param p Client The ATS clientstructure.622 * @param pInst The opaque ATS instance structure. 621 623 * @param pPktHdr The test set end packet. 622 624 */ 623 static int atsDoTestSetSend(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)625 static int atsDoTestSetSend(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 624 626 { 625 627 if (pPktHdr->cb != sizeof(ATSPKTREQTSETSND)) 626 return atsReplyBadSize(pThis, p Client, pPktHdr, sizeof(ATSPKTREQTSETSND));628 return atsReplyBadSize(pThis, pInst, pPktHdr, sizeof(ATSPKTREQTSETSND)); 627 629 628 630 PATSPKTREQTSETSND pReq = (PATSPKTREQTSETSND)pPktHdr; … … 631 633 632 634 if (!pThis->Callbacks.pfnTestSetSendRead) 633 return atsReplyRC(pThis, p Client, pPktHdr, VERR_NOT_SUPPORTED, "Sending test set not implemented");635 return atsReplyRC(pThis, pInst, pPktHdr, VERR_NOT_SUPPORTED, "Sending test set not implemented"); 634 636 635 637 if (pThis->Callbacks.pfnTestSetSendBegin) … … 637 639 rc = pThis->Callbacks.pfnTestSetSendBegin(pThis->Callbacks.pvUser, pReq->szTag); 638 640 if (RT_FAILURE(rc)) 639 return atsReplyRC(pThis, p Client, pPktHdr, rc, "Beginning sending test set '%s' failed", pReq->szTag);641 return atsReplyRC(pThis, pInst, pPktHdr, rc, "Beginning sending test set '%s' failed", pReq->szTag); 640 642 } 641 643 … … 650 652 char abPadding[ATSPKT_ALIGNMENT]; 651 653 } Pkt; 654 #ifdef DEBUG 655 RT_ZERO(Pkt); 656 #endif 652 657 size_t cbRead = 0; 653 658 rc = pThis->Callbacks.pfnTestSetSendRead(pThis->Callbacks.pvUser, pReq->szTag, &Pkt.ab, sizeof(Pkt.ab), &cbRead); … … 659 664 { 660 665 Pkt.uCrc32 = RTCrc32Finish(uMyCrc32); 661 rc = atsReplyInternal(pThis, p Client, &Pkt.Hdr, "DATA EOF", sizeof(uint32_t) /* uCrc32 */);666 rc = atsReplyInternal(pThis, pInst, &Pkt.Hdr, "DATA EOF", sizeof(uint32_t) /* uCrc32 */); 662 667 if (RT_SUCCESS(rc)) 663 rc = atsWaitForAck(pThis, p Client, &Pkt.Hdr);668 rc = atsWaitForAck(pThis, pInst, &Pkt.Hdr); 664 669 } 665 670 else 666 rc = atsReplyRC(pThis, p Client, pPktHdr, rc, "Sending data for test set '%s' failed", pReq->szTag);671 rc = atsReplyRC(pThis, pInst, pPktHdr, rc, "Sending data for test set '%s' failed", pReq->szTag); 667 672 break; 668 673 } … … 671 676 Pkt.uCrc32 = RTCrc32Finish(uMyCrc32); 672 677 678 Log2Func(("cbRead=%zu -> uCrc32=%#x\n", cbRead, Pkt.uCrc32)); 679 673 680 Assert(cbRead <= sizeof(Pkt.ab)); 674 681 675 rc = atsReplyInternal(pThis, p Client, &Pkt.Hdr, "DATA ", sizeof(uint32_t) /* uCrc32 */ + cbRead);682 rc = atsReplyInternal(pThis, pInst, &Pkt.Hdr, "DATA ", sizeof(uint32_t) /* uCrc32 */ + cbRead); 676 683 if (RT_FAILURE(rc)) 677 684 break; 678 685 679 rc = atsWaitForAck(pThis, p Client, &Pkt.Hdr);686 rc = atsWaitForAck(pThis, pInst, &Pkt.Hdr); 680 687 if (RT_FAILURE(rc)) 681 688 break; … … 686 693 int rc2 = pThis->Callbacks.pfnTestSetSendEnd(pThis->Callbacks.pvUser, pReq->szTag); 687 694 if (RT_FAILURE(rc2)) 688 return atsReplyRC(pThis, p Client, pPktHdr, rc2, "Ending sending test set '%s' failed", pReq->szTag);695 return atsReplyRC(pThis, pInst, pPktHdr, rc2, "Ending sending test set '%s' failed", pReq->szTag); 689 696 } 690 697 … … 697 704 * @returns IPRT status code. 698 705 * @param pThis The ATS instance. 699 * @param p Client The ATS clientstructure.706 * @param pInst The opaque ATS instance structure. 700 707 * @param pPktHdr The packet header. 701 708 */ 702 static int atsDoTonePlay(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)709 static int atsDoTonePlay(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 703 710 { 704 711 int rc = VINF_SUCCESS; 705 712 706 713 if (pPktHdr->cb < sizeof(ATSPKTREQTONEPLAY)) 707 return atsReplyBadSize(pThis, p Client, pPktHdr, sizeof(ATSPKTREQTONEPLAY));708 709 if (p Client->enmState != ATSCLIENTSTATE_READY)710 return atsReplyInvalidState(pThis, p Client, pPktHdr);714 return atsReplyBadSize(pThis, pInst, pPktHdr, sizeof(ATSPKTREQTONEPLAY)); 715 716 if (pInst->enmState != ATSCLIENTSTATE_READY) 717 return atsReplyInvalidState(pThis, pInst, pPktHdr); 711 718 712 719 if (!pThis->Callbacks.pfnTonePlay) 713 return atsReplyRC(pThis, p Client, pPktHdr, VERR_NOT_SUPPORTED, "Playing tones not supported");720 return atsReplyRC(pThis, pInst, pPktHdr, VERR_NOT_SUPPORTED, "Playing tones not supported"); 714 721 715 722 PATSPKTREQTONEPLAY pReq = (PATSPKTREQTONEPLAY)pPktHdr; 716 723 rc = pThis->Callbacks.pfnTonePlay(pThis->Callbacks.pvUser, &pReq->ToneParms); 717 724 718 int rc2 = atsReplyAck(pThis, p Client, pPktHdr);725 int rc2 = atsReplyAck(pThis, pInst, pPktHdr); 719 726 if (RT_SUCCESS(rc)) 720 727 rc = rc2; … … 728 735 * @returns IPRT status code. 729 736 * @param pThis The ATS instance. 730 * @param p Client The ATS clientstructure.737 * @param pInst The opaque ATS instance structure. 731 738 * @param pPktHdr The packet header. 732 739 */ 733 static int atsDoToneRecord(PATSSERVER pThis, PATS CLIENTINST pClient, PATSPKTHDR pPktHdr)740 static int atsDoToneRecord(PATSSERVER pThis, PATSSERVERINST pInst, PATSPKTHDR pPktHdr) 734 741 { 735 742 int rc = VINF_SUCCESS; 736 743 737 744 if (pPktHdr->cb < sizeof(ATSPKTREQTONEREC)) 738 return atsReplyBadSize(pThis, p Client, pPktHdr, sizeof(ATSPKTREQTONEREC));739 740 if (p Client->enmState != ATSCLIENTSTATE_READY)741 return atsReplyInvalidState(pThis, p Client, pPktHdr);745 return atsReplyBadSize(pThis, pInst, pPktHdr, sizeof(ATSPKTREQTONEREC)); 746 747 if (pInst->enmState != ATSCLIENTSTATE_READY) 748 return atsReplyInvalidState(pThis, pInst, pPktHdr); 742 749 743 750 if (!pThis->Callbacks.pfnToneRecord) 744 return atsReplyRC(pThis, p Client, pPktHdr, VERR_NOT_SUPPORTED, "Recording tones not supported");751 return atsReplyRC(pThis, pInst, pPktHdr, VERR_NOT_SUPPORTED, "Recording tones not supported"); 745 752 746 753 PATSPKTREQTONEREC pReq = (PATSPKTREQTONEREC)pPktHdr; 747 754 rc = pThis->Callbacks.pfnToneRecord(pThis->Callbacks.pvUser, &pReq->ToneParms); 748 755 749 int rc2 = atsReplyAck(pThis, p Client, pPktHdr);756 int rc2 = atsReplyAck(pThis, pInst, pPktHdr); 750 757 if (RT_SUCCESS(rc)) 751 758 rc = rc2; … … 759 766 * @returns IPRT status code. 760 767 * @param pThis The ATS instance. 761 * @param p Client The ATS client structure sending the request.762 */ 763 static int atsClientReqProcess(PATSSERVER pThis, PATS CLIENTINST pClient)768 * @param pInst The ATS client structure sending the request. 769 */ 770 static int atsClientReqProcess(PATSSERVER pThis, PATSSERVERINST pInst) 764 771 { 765 772 /* … … 767 774 */ 768 775 PATSPKTHDR pPktHdr = NULL; 769 int rc = atsRecvPkt(pThis, p Client, &pPktHdr, true /*fAutoRetryOnFailure*/);776 int rc = atsRecvPkt(pThis, pInst, &pPktHdr, true /*fAutoRetryOnFailure*/); 770 777 if (RT_FAILURE(rc)) 771 778 return rc; … … 776 783 /* Connection: */ 777 784 if ( atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_HOWDY)) 778 rc = atsDoHowdy(pThis, p Client, pPktHdr);785 rc = atsDoHowdy(pThis, pInst, pPktHdr); 779 786 else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_BYE)) 780 rc = atsDoBye(pThis, p Client, pPktHdr);787 rc = atsDoBye(pThis, pInst, pPktHdr); 781 788 /* Test set handling: */ 782 789 else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TESTSET_BEGIN)) 783 rc = atsDoTestSetBegin(pThis, p Client, pPktHdr);790 rc = atsDoTestSetBegin(pThis, pInst, pPktHdr); 784 791 else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TESTSET_END)) 785 rc = atsDoTestSetEnd(pThis, p Client, pPktHdr);792 rc = atsDoTestSetEnd(pThis, pInst, pPktHdr); 786 793 else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TESTSET_SEND)) 787 rc = atsDoTestSetSend(pThis, p Client, pPktHdr);794 rc = atsDoTestSetSend(pThis, pInst, pPktHdr); 788 795 /* Audio testing: */ 789 796 else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TONE_PLAY)) 790 rc = atsDoTonePlay(pThis, p Client, pPktHdr);797 rc = atsDoTonePlay(pThis, pInst, pPktHdr); 791 798 else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TONE_RECORD)) 792 rc = atsDoToneRecord(pThis, p Client, pPktHdr);799 rc = atsDoToneRecord(pThis, pInst, pPktHdr); 793 800 /* Misc: */ 794 801 else 795 rc = atsReplyUnknown(pThis, p Client, pPktHdr);802 rc = atsReplyUnknown(pThis, pInst, pPktHdr); 796 803 797 804 RTMemFree(pPktHdr); … … 804 811 * 805 812 * @returns nothing. 806 * @param p Client The ATS clientstructure.807 */ 808 static void atsClientDestroy(PATS CLIENTINST pClient)809 { 810 if (p Client->pszHostname)811 RTStrFree(p Client->pszHostname);812 RTMemFree(p Client);813 * @param pInst The opaque ATS instance structure. 814 */ 815 static void atsClientDestroy(PATSSERVERINST pInst) 816 { 817 if (pInst->pszHostname) 818 RTStrFree(pInst->pszHostname); 819 RTMemFree(pInst); 813 820 } 814 821 … … 825 832 unsigned cClientsMax = 0; 826 833 unsigned cClientsCur = 0; 827 PATS CLIENTINST *papClients = NULL;834 PATSSERVERINST *papInsts = NULL; 828 835 829 836 /* Add the pipe to the poll set. */ … … 853 860 RTCritSectEnter(&pThis->CritSectClients); 854 861 /* Walk the list and add all new clients. */ 855 PATS CLIENTINST pIt, pItNext;862 PATSSERVERINST pIt, pItNext; 856 863 RTListForEachSafe(&pThis->LstClientsNew, pIt, pItNext, ATSCLIENTINST, NdLst) 857 864 { … … 861 868 { 862 869 /* Realloc to accommodate for the new clients. */ 863 PATS CLIENTINST *papClientsNew = (PATSCLIENTINST *)RTMemRealloc(papClients, (cClientsMax + 10) * sizeof(PATSCLIENTINST));864 if (RT_LIKELY(pap ClientsNew))870 PATSSERVERINST *papInstsNew = (PATSSERVERINST *)RTMemRealloc(papInsts, (cClientsMax + 10) * sizeof(PATSSERVERINST)); 871 if (RT_LIKELY(papInstsNew)) 865 872 { 866 873 cClientsMax += 10; 867 pap Clients = papClientsNew;874 papInsts = papInstsNew; 868 875 } 869 876 } … … 873 880 unsigned idxSlt = 0; 874 881 while ( idxSlt < cClientsMax 875 && pap Clients[idxSlt] != NULL)882 && papInsts[idxSlt] != NULL) 876 883 idxSlt++; 877 884 878 rc = pThis->pTransport->pfnPollSetAdd( &pThis->TransportInst, pThis->hPollSet, pIt->pTransportClient, idxSlt + 1);885 rc = pThis->pTransport->pfnPollSetAdd(pThis->pTransportInst, pThis->hPollSet, pIt->pTransportClient, idxSlt + 1); 879 886 if (RT_SUCCESS(rc)) 880 887 { 881 888 cClientsCur++; 882 pap Clients[idxSlt] = pIt;889 papInsts[idxSlt] = pIt; 883 890 } 884 891 else 885 892 { 886 pThis->pTransport->pfnNotifyBye( &pThis->TransportInst, pIt->pTransportClient);893 pThis->pTransport->pfnNotifyBye(pThis->pTransportInst, pIt->pTransportClient); 887 894 atsClientDestroy(pIt); 888 895 } … … 890 897 else 891 898 { 892 pThis->pTransport->pfnNotifyBye( &pThis->TransportInst, pIt->pTransportClient);899 pThis->pTransport->pfnNotifyBye(pThis->pTransportInst, pIt->pTransportClient); 893 900 atsClientDestroy(pIt); 894 901 } … … 899 906 { 900 907 /* Client sends a request, pick the right client and process it. */ 901 PATS CLIENTINST pClient = papClients[uId - 1];902 AssertPtr(p Client);908 PATSSERVERINST pInst = papInsts[uId - 1]; 909 AssertPtr(pInst); 903 910 if (fEvts & RTPOLL_EVT_READ) 904 rc = atsClientReqProcess(pThis, p Client);911 rc = atsClientReqProcess(pThis, pInst); 905 912 906 913 if ( (fEvts & RTPOLL_EVT_ERROR) … … 908 915 { 909 916 /* Close connection and remove client from array. */ 910 rc = pThis->pTransport->pfnPollSetRemove( &pThis->TransportInst, pThis->hPollSet, pClient->pTransportClient, uId);917 rc = pThis->pTransport->pfnPollSetRemove(pThis->pTransportInst, pThis->hPollSet, pInst->pTransportClient, uId); 911 918 AssertRC(rc); 912 919 913 pThis->pTransport->pfnNotifyBye( &pThis->TransportInst, pClient->pTransportClient);914 pap Clients[uId - 1] = NULL;920 pThis->pTransport->pfnNotifyBye(pThis->pTransportInst, pInst->pTransportClient); 921 papInsts[uId - 1] = NULL; 915 922 cClientsCur--; 916 atsClientDestroy(p Client);923 atsClientDestroy(pInst); 917 924 } 918 925 } … … 929 936 * @returns VBox status code. 930 937 */ 931 static DECLCALLBACK(int) ats MainThread(RTTHREAD hThread, void *pvUser)938 static DECLCALLBACK(int) atsConnectThread(RTTHREAD hThread, void *pvUser) 932 939 { 933 940 RT_NOREF(hThread); … … 946 953 */ 947 954 PATSTRANSPORTCLIENT pTransportClient; 948 rc = pThis->pTransport->pfnWaitForConnect( &pThis->TransportInst, &pTransportClient);955 rc = pThis->pTransport->pfnWaitForConnect(pThis->pTransportInst, &pTransportClient); 949 956 if (RT_FAILURE(rc)) 950 957 continue; … … 954 961 * the request handling thread. 955 962 */ 956 PATS CLIENTINST pClient = (PATSCLIENTINST)RTMemAllocZ(sizeof(ATSCLIENTINST));957 if (RT_LIKELY(p Client))963 PATSSERVERINST pInst = (PATSSERVERINST)RTMemAllocZ(sizeof(ATSCLIENTINST)); 964 if (RT_LIKELY(pInst)) 958 965 { 959 p Client->enmState = ATSCLIENTSTATE_INITIALISING;960 p Client->pTransportClient = pTransportClient;961 p Client->pszHostname = NULL;966 pInst->enmState = ATSCLIENTSTATE_INITIALISING; 967 pInst->pTransportClient = pTransportClient; 968 pInst->pszHostname = NULL; 962 969 963 970 /* Add client to the new list and inform the worker thread. */ 964 971 RTCritSectEnter(&pThis->CritSectClients); 965 RTListAppend(&pThis->LstClientsNew, &p Client->NdLst);972 RTListAppend(&pThis->LstClientsNew, &pInst->NdLst); 966 973 RTCritSectLeave(&pThis->CritSectClients); 967 974 … … 974 981 { 975 982 RTMsgError("Creating new client structure failed with out of memory error\n"); 976 pThis->pTransport->pfnNotifyBye( &pThis->TransportInst, pTransportClient);983 pThis->pTransport->pfnNotifyBye(pThis->pTransportInst, pTransportClient); 977 984 } 978 985 } … … 982 989 983 990 /** 984 * Initializes the global ATS state.991 * Creates an ATS instance. 985 992 * 986 993 * @returns VBox status code. 987 * @param pThis The ATS instance. 988 * @param pszBindAddr Bind address. Empty means any address. 989 * If set to NULL, "127.0.0.1" will be used. 990 * @param uBindPort Bind port. If set to 0, ATS_DEFAULT_PORT is being used. 991 * @param pCallbacks The callbacks table to use. 992 * */ 993 int AudioTestSvcInit(PATSSERVER pThis, 994 const char *pszBindAddr, uint32_t uBindPort, PCATSCALLBACKS pCallbacks) 995 { 996 memcpy(&pThis->Callbacks, pCallbacks, sizeof(ATSCALLBACKS)); 997 998 pThis->fStarted = false; 999 pThis->fTerminate = false; 1000 1001 pThis->hPipeR = NIL_RTPIPE; 1002 pThis->hPipeW = NIL_RTPIPE; 1003 1004 RTListInit(&pThis->LstClientsNew); 1005 994 * @param pThis The ATS instance to create. 995 */ 996 int AudioTestSvcCreate(PATSSERVER pThis) 997 { 1006 998 /* 1007 999 * The default transporter is the first one. 1008 1000 */ 1009 pThis->pTransport = g_apTransports[0]; 1001 pThis->pTransport = g_apTransports[0]; /** @todo Make this dynamic. */ 1002 1003 return pThis->pTransport->pfnCreate(&pThis->pTransportInst); 1004 } 1005 1006 /** 1007 * Initializes an ATS instance. 1008 * 1009 * @returns VBox status code. 1010 * @param pThis The ATS instance. 1011 * @param pCallbacks The callbacks table to use. 1012 */ 1013 int AudioTestSvcInit(PATSSERVER pThis, PCATSCALLBACKS pCallbacks) 1014 { 1015 memcpy(&pThis->Callbacks, pCallbacks, sizeof(ATSCALLBACKS)); 1016 1017 pThis->fStarted = false; 1018 pThis->fTerminate = false; 1019 1020 pThis->hPipeR = NIL_RTPIPE; 1021 pThis->hPipeW = NIL_RTPIPE; 1022 1023 RTListInit(&pThis->LstClientsNew); 1010 1024 1011 1025 /* 1012 1026 * Initialize the transport layer. 1013 1027 */ 1014 int rc = pThis->pTransport->pfnInit(&pThis->TransportInst, pszBindAddr ? pszBindAddr : ATS_TCP_HOST_DEFAULT_ADDR_STR, 1015 uBindPort ? uBindPort : ATS_TCP_HOST_DEFAULT_PORT); 1028 int rc = RTCritSectInit(&pThis->CritSectClients); 1016 1029 if (RT_SUCCESS(rc)) 1017 1030 { 1018 rc = RT CritSectInit(&pThis->CritSectClients);1031 rc = RTPollSetCreate(&pThis->hPollSet); 1019 1032 if (RT_SUCCESS(rc)) 1020 1033 { 1021 rc = RTP ollSetCreate(&pThis->hPollSet);1034 rc = RTPipeCreate(&pThis->hPipeR, &pThis->hPipeW, 0); 1022 1035 if (RT_SUCCESS(rc)) 1023 1036 { 1024 rc = RTPipeCreate(&pThis->hPipeR, &pThis->hPipeW, 0); 1037 /* Spin off the thread serving connections. */ 1038 rc = RTThreadCreate(&pThis->hThreadServing, atsClientWorker, pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, 1039 "AUDTSTSRVC"); 1025 1040 if (RT_SUCCESS(rc)) 1026 { 1027 /* Spin off the thread serving connections. */ 1028 rc = RTThreadCreate(&pThis->hThreadServing, atsClientWorker, pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, 1029 "AUDTSTSRVC"); 1030 if (RT_SUCCESS(rc)) 1031 return VINF_SUCCESS; 1032 else 1033 RTMsgError("Creating the client worker thread failed with %Rrc\n", rc); 1034 1035 RTPipeClose(pThis->hPipeR); 1036 RTPipeClose(pThis->hPipeW); 1037 } 1041 return VINF_SUCCESS; 1038 1042 else 1039 RTMsgError("Creating communications pipe failed with %Rrc\n", rc); 1040 1041 RTPollSetDestroy(pThis->hPollSet); 1043 RTMsgError("Creating the client worker thread failed with %Rrc\n", rc); 1044 1045 RTPipeClose(pThis->hPipeR); 1046 RTPipeClose(pThis->hPipeW); 1042 1047 } 1043 1048 else 1044 RTMsgError("Creating pollsetfailed with %Rrc\n", rc);1045 1046 RT CritSectDelete(&pThis->CritSectClients);1049 RTMsgError("Creating communications pipe failed with %Rrc\n", rc); 1050 1051 RTPollSetDestroy(pThis->hPollSet); 1047 1052 } 1048 1053 else 1049 RTMsgError("Creating global critical section failed with %Rrc\n", rc); 1054 RTMsgError("Creating pollset failed with %Rrc\n", rc); 1055 1056 RTCritSectDelete(&pThis->CritSectClients); 1050 1057 } 1051 1058 else 1052 RTMsgError("Initializing the transport layer failed with %Rrc\n", rc); 1053 1054 return rc; 1059 RTMsgError("Creating global critical section failed with %Rrc\n", rc); 1060 1061 return rc; 1062 } 1063 1064 /** 1065 * Handles a command line option. 1066 * 1067 * @returns VBox status code. 1068 * @param pThis The ATS instance to handle option for. 1069 * @param ch Option (short) to handle. 1070 * @param pVal Option union to store the result in on success. 1071 */ 1072 int AudioTestSvcHandleOption(PATSSERVER pThis, int ch, PCRTGETOPTUNION pVal) 1073 { 1074 AssertPtrReturn(pThis->pTransport, VERR_WRONG_ORDER); /* Must be creatd first. */ 1075 if (!pThis->pTransport->pfnOption) 1076 return VERR_GETOPT_UNKNOWN_OPTION; 1077 return pThis->pTransport->pfnOption(pThis->pTransportInst, ch, pVal); 1055 1078 } 1056 1079 … … 1059 1082 * 1060 1083 * @returns VBox status code. 1061 * @param pThis The ATS instance .1084 * @param pThis The ATS instance to start. 1062 1085 */ 1063 1086 int AudioTestSvcStart(PATSSERVER pThis) 1064 1087 { 1065 /* Spin off the main thread. */ 1066 int rc = RTThreadCreate(&pThis->hThreadMain, atsMainThread, pThis, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, 1088 int rc = pThis->pTransport->pfnStart(pThis->pTransportInst); 1089 if (RT_SUCCESS(rc)) 1090 { 1091 /* Spin off the connection thread. */ 1092 rc = RTThreadCreate(&pThis->hThreadMain, atsConnectThread, pThis, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, 1067 1093 "AUDTSTSRVM"); 1068 if (RT_SUCCESS(rc))1069 {1070 rc = RTThreadUserWait(pThis->hThreadMain, RT_MS_30SEC);1071 1094 if (RT_SUCCESS(rc)) 1072 pThis->fStarted = true; 1095 { 1096 rc = RTThreadUserWait(pThis->hThreadMain, RT_MS_30SEC); 1097 if (RT_SUCCESS(rc)) 1098 pThis->fStarted = true; 1099 } 1073 1100 } 1074 1101 … … 1090 1117 1091 1118 if (pThis->pTransport) 1092 pThis->pTransport->pfnTerm( &pThis->TransportInst);1119 pThis->pTransport->pfnTerm(pThis->pTransportInst); 1093 1120 1094 1121 size_t cbWritten; … … 1149 1176 pThis->pTransport = NULL; 1150 1177 1151 PATS CLIENTINST pIt, pItNext;1178 PATSSERVERINST pIt, pItNext; 1152 1179 RTListForEachSafe(&pThis->LstClientsNew, pIt, pItNext, ATSCLIENTINST, NdLst) 1153 1180 { … … 1175 1202 int AudioTestSvcDestroy(PATSSERVER pThis) 1176 1203 { 1177 return audioTestSvcDestroyInternal(pThis); 1178 } 1179 1204 int rc = audioTestSvcDestroyInternal(pThis); 1205 if (RT_SUCCESS(rc)) 1206 { 1207 if (pThis->pTransport) 1208 { 1209 if ( pThis->pTransport->pfnDestroy 1210 && pThis->pTransportInst) 1211 { 1212 pThis->pTransport->pfnDestroy(pThis->pTransportInst); 1213 pThis->pTransportInst = NULL; 1214 } 1215 } 1216 } 1217 1218 return rc; 1219 } -
trunk/src/VBox/Devices/Audio/AudioTestService.h
r89614 r89962 22 22 #endif 23 23 24 #include <iprt/tcp.h> 25 24 26 #include "AudioTestServiceInternal.h" 25 27 28 extern const PCATSTRANSPORT g_apTransports[]; 29 extern const size_t g_cTransports; 26 30 27 /** Default TCP/IP port the host ATS (Audio Test Service) is running on. */ 28 #define ATS_TCP_HOST_DEFAULT_PORT 6052 29 /** Default TCP/IP address the host ATS (Audio Test Service) is running on. */ 30 #define ATS_TCP_HOST_DEFAULT_ADDR_STR "127.0.0.1" 31 /** Default TCP/IP port the guest ATS (Audio Test Service) is running on. */ 32 #define ATS_TCP_GUEST_DEFAULT_PORT 6042 31 /** Default TCP/IP bind port the guest ATS (Audio Test Service) is listening on. */ 32 #define ATS_TCP_DEF_BIND_PORT_GUEST 6052 33 /** Default TCP/IP bind port the host ATS is listening on. */ 34 #define ATS_TCP_DEF_BIND_PORT_HOST 6042 35 /** Default TCP/IP ATS bind port the ValidationKit Audio Driver ATS is listening on. */ 36 #define ATS_TCP_DEF_BIND_PORT_VALKIT 6052 37 /** Default TCP/IP port the guest ATS is connecting to. */ 38 #define ATS_TCP_DEF_CONNECT_PORT_GUEST ATS_TCP_DEF_BIND_PORT_HOST 39 /** Default TCP/IP port the host ATS is connecting to the guest (needs NAT port forwarding). */ 40 #define ATS_TCP_DEF_CONNECT_PORT_HOST_PORT_FWD 6062 41 /** Default TCP/IP port the host ATS is connecting to. */ 42 #define ATS_TCP_DEF_CONNECT_PORT_VALKIT ATS_TCP_DEF_BIND_PORT_VALKIT 43 /** Default TCP/IP address the host is connecting to. */ 44 #define ATS_TCP_DEF_CONNECT_HOST_ADDR_STR "127.0.0.1" 45 /** Default TCP/IP address the guest ATS connects to when 46 * running in client mode (reversed mode, needed for NATed VMs). */ 47 #define ATS_TCP_DEF_CONNECT_GUEST_STR "10.0.2.2" 33 48 34 49 /** … … 110 125 111 126 /** 112 * Structure for keeping Audio Test Service (ATS) transport instance-specific data.113 *114 * Currently only TCP/IP is supported.115 */116 typedef struct ATSTRANSPORTINST117 {118 /** The addresses to bind to. Empty string means any. */119 char szTcpBindAddr[256];120 /** The TCP port to listen to. */121 uint32_t uTcpBindPort;122 /** Pointer to the TCP server instance. */123 PRTTCPSERVER pTcpServer;124 } ATSTRANSPORTINST;125 /** Pointer to an Audio Test Service (ATS) TCP/IP transport instance. */126 typedef ATSTRANSPORTINST *PATSTRANSPORTINSTTCP;127 128 /**129 127 * Structure for keeping an Audio Test Service (ATS) instance. 130 128 */ 131 129 typedef struct ATSSERVER 132 130 { 133 /** The selected transport layer. */131 /** Pointer to the selected transport layer. */ 134 132 PCATSTRANSPORT pTransport; 135 /** The transport instance. */136 ATSTRANSPORTINSTTransportInst;133 /** Pointer to the transport instance. */ 134 PATSTRANSPORTINST pTransportInst; 137 135 /** The callbacks table. */ 138 136 ATSCALLBACKS Callbacks; … … 159 157 typedef ATSSERVER *PATSSERVER; 160 158 161 int AudioTestSvcInit(PATSSERVER pThis, const char *pszBindAddr, uint32_t uBindPort, PCATSCALLBACKS pCallbacks); 159 int AudioTestSvcCreate(PATSSERVER pThis); 160 int AudioTestSvcInit(PATSSERVER pThis, PCATSCALLBACKS pCallbacks); 162 161 int AudioTestSvcDestroy(PATSSERVER pThis); 162 int AudioTestSvcHandleOption(PATSSERVER pThis, int ch, PCRTGETOPTUNION pVal); 163 163 int AudioTestSvcStart(PATSSERVER pThis); 164 164 int AudioTestSvcShutdown(PATSSERVER pThis); 165 165 166 /** TCP/IP options for the ATS server. 167 * @todo Make this more abstract later. */ 168 enum ATSTCPOPT 169 { 170 ATSTCPOPT_MODE = 5000, 171 ATSTCPOPT_BIND_ADDRESS, 172 ATSTCPOPT_BIND_PORT, 173 ATSTCPOPT_CONNECT_ADDRESS, 174 ATSTCPOPT_CONNECT_PORT 175 }; 176 166 177 #endif /* !VBOX_INCLUDED_SRC_Audio_AudioTestService_h */ 167 178 -
trunk/src/VBox/Devices/Audio/AudioTestServiceClient.cpp
r89807 r89962 22 22 * Header Files * 23 23 *********************************************************************************************************************************/ 24 #define LOG_GROUP RTLOGGROUP_DEFAULT 25 #include <VBox/log.h> 24 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO /** @todo Add an own log group for this? */ 26 25 27 26 #include <iprt/crc.h> … … 32 31 #include <iprt/tcp.h> 33 32 33 #include <VBox/log.h> 34 34 35 #include "AudioTestService.h" 35 #include "AudioTestService Protocol.h"36 #include "AudioTestServiceInternal.h" 36 37 #include "AudioTestServiceClient.h" 37 38 … … 45 46 { 46 47 char szOp[ATSPKT_OPCODE_MAX_LEN]; 48 /** Pointer to payload data. 49 * This does *not* include the header! */ 47 50 void *pvPayload; 51 /** Size (in bytes) of the payload data. 52 * This does *not* include the header! */ 48 53 size_t cbPayload; 49 54 } ATSSRVREPLY; … … 59 64 static void audioTestSvcClientInit(PATSCLIENT pClient) 60 65 { 61 pClient->cbHdr = 0; 62 pClient->hSock = NIL_RTSOCKET; 66 RT_BZERO(pClient, sizeof(ATSCLIENT)); 63 67 } 64 68 … … 94 98 static int audioTestSvcClientRecvReply(PATSCLIENT pClient, PATSSRVREPLY pReply, bool fNoDataOk) 95 99 { 96 int rc;97 98 100 LogFlowFuncEnter(); 99 101 100 ATSPKTHDR Hdr; 101 RT_ZERO(Hdr); 102 size_t cbHdr = 0; 103 if (pClient->cbHdr) /* Header already received? */ 102 PATSPKTHDR pPktHdr; 103 int rc = pClient->pTransport->pfnRecvPkt(pClient->pTransportInst, pClient->pTransportClient, &pPktHdr); 104 if (RT_SUCCESS(rc)) 104 105 { 105 memcpy(&Hdr, &pClient->abHdr, sizeof(Hdr)); 106 cbHdr = pClient->cbHdr; 107 pClient->cbHdr = 0; 108 rc = VINF_SUCCESS; 109 } 110 else /* No, receive header. */ 111 { 112 rc = RTTcpRead(pClient->hSock, &Hdr, sizeof(Hdr), &cbHdr); 113 } 114 115 LogFlowFunc(("rc=%Rrc, hdr=%zu, hdr.cb=%zu, %.8s -> %.*Rhxd\n", rc, cbHdr, Hdr.cb, Hdr.achOpcode, RT_MIN(cbHdr, sizeof(ATSPKTHDR)), &Hdr)); 116 117 if (RT_FAILURE(rc)) 118 return rc; 119 120 if (cbHdr != sizeof(Hdr)) /* Check for bad packet sizes. */ 121 { 122 AssertMsgFailed(("Packet is invalid (%RU32 bytes), must be at least %zu bytes\n", cbHdr, sizeof(Hdr))); 123 return VERR_NET_INCOMPLETE_TX_PACKET; 124 } 125 126 if (Hdr.cb < sizeof(ATSPKTHDR)) 127 { 128 AssertMsgFailed(("Packet is too small (%RU32 bytes), must be at least %zu bytes\n", Hdr.cb, sizeof(Hdr))); 129 return VERR_NET_INCOMPLETE_TX_PACKET; 130 } 131 132 if (Hdr.cb > ATSPKT_MAX_SIZE) 133 { 134 AssertMsgFailed(("Packet is %RU32 bytes, only %zu bytes allowed\n", Hdr.cb, ATSPKT_MAX_SIZE)); 135 return VERR_BUFFER_OVERFLOW; 136 } 137 138 if (Hdr.cb > ATSPKT_MAX_SIZE) 139 { 140 AssertMsgFailed(("Packet is %RU32 bytes, only %zu bytes allowed\n", Hdr.cb, ATSPKT_MAX_SIZE)); 141 return VERR_BUFFER_OVERFLOW; 142 } 143 144 pReply->cbPayload = Hdr.cb - sizeof(ATSPKTHDR); 145 Log3Func(("cbHdr=%zu, Hdr.szOp=%s, Hdr.cb=%RU32 -> %zu bytes payload\n", cbHdr, Hdr.achOpcode, Hdr.cb, pReply->cbPayload)); 146 if (pReply->cbPayload) 147 { 148 pReply->pvPayload = RTMemAlloc(pReply->cbPayload); 149 if (pReply->pvPayload) 106 AssertReturn(pPktHdr->cb >= sizeof(ATSPKTHDR), VERR_NET_PROTOCOL_ERROR); 107 pReply->cbPayload = pPktHdr->cb - sizeof(ATSPKTHDR); 108 Log3Func(("szOp=%.8s, cb=%RU32\n", pPktHdr->achOpcode, pPktHdr->cb)); 109 if (pReply->cbPayload) 150 110 { 151 uint32_t cbPayloadRead = 0; 152 while (cbPayloadRead < pReply->cbPayload) 153 { 154 size_t cbRead = 0; 155 rc = RTTcpRead(pClient->hSock, (uint8_t *)pReply->pvPayload + cbPayloadRead, pReply->cbPayload - cbPayloadRead, &cbRead); 156 if (RT_SUCCESS(rc)) 157 { 158 if (!cbRead) 159 { 160 memcpy(&pClient->abHdr, &Hdr, sizeof(pClient->abHdr)); 161 if (!fNoDataOk) 162 rc = VERR_NET_PROTOCOL_ERROR; 163 } 164 165 cbPayloadRead += (uint32_t)cbRead; 166 Assert(cbPayloadRead <= pReply->cbPayload); 167 } 168 } 169 170 if (RT_SUCCESS(rc)) 171 { 172 Assert(cbPayloadRead == pReply->cbPayload); 173 if (Hdr.uCrc32) /* Checksum given? */ 174 { 175 uint32_t uMyCrc32 = RTCrc32Start(); 176 uMyCrc32 = RTCrc32Process(uMyCrc32, Hdr.achOpcode, sizeof(Hdr.achOpcode)); 177 uMyCrc32 = RTCrc32Process(uMyCrc32, pReply->pvPayload, pReply->cbPayload); 178 179 if (Hdr.uCrc32 != RTCrc32Finish(uMyCrc32)) 180 AssertFailedStmt(rc = VERR_TAR_CHKSUM_MISMATCH /** @todo Fudge! */); 181 182 if (RT_SUCCESS(rc)) 183 { 184 /* Make sure to align the payload data (if not done by the sender already). */ 185 size_t const cbRestAlignment = RT_ALIGN_Z(pReply->cbPayload, ATSPKT_ALIGNMENT) - pReply->cbPayload; 186 if (cbRestAlignment) 187 { 188 uint8_t abAlignment[ATSPKT_ALIGNMENT]; 189 rc = RTTcpRead(pClient->hSock, abAlignment, RT_MIN(cbRestAlignment, sizeof(abAlignment)), NULL); 190 } 191 } 192 } 193 } 194 195 if (RT_FAILURE(rc)) 196 audioTestSvcClientReplyDestroy(pReply); 111 pReply->pvPayload = RTMemDup((uint8_t *)pPktHdr + sizeof(ATSPKTHDR), pReply->cbPayload); 197 112 } 198 113 else 199 rc = VERR_NO_MEMORY; 114 pReply->pvPayload = NULL; 115 116 if ( !pReply->cbPayload 117 && !fNoDataOk) 118 { 119 rc = VERR_NET_PROTOCOL_ERROR; 120 } 121 else 122 { 123 memcpy(&pReply->szOp, &pPktHdr->achOpcode, sizeof(pReply->szOp)); 124 } 125 126 RTMemFree(pPktHdr); 127 pPktHdr = NULL; 200 128 } 201 202 if (RT_SUCCESS(rc))203 memcpy(pReply->szOp, Hdr.achOpcode, sizeof(pReply->szOp));204 129 205 130 LogFlowFuncLeaveRC(rc); … … 232 157 233 158 /** 234 * Sends data over the transport to the server.235 * For now only TCP/IP is implemented.236 *237 * @returns VBox status code.238 * @param pClient Client to send data for.239 * @param pvData Pointer to data to send.240 * @param cbData Size (in bytes) of \a pvData to send.241 */242 static int audioTestSvcClientSend(PATSCLIENT pClient, const void *pvData, size_t cbData)243 {244 return RTTcpWrite(pClient->hSock, pvData, cbData);245 }246 247 /**248 159 * Sends a message plus optional payload to an ATS server. 249 160 * … … 252 163 * @param pvHdr Pointer to header data to send. 253 164 * @param cbHdr Size (in bytes) of \a pvHdr to send. 254 * @param pvPayload Pointer to payload to send. Optional. 255 * @param cbPayload Size (in bytes) of \a pvPayload to send. Set to 0 if no payload needed. 256 */ 257 static int audioTestSvcClientSendMsg(PATSCLIENT pClient, 258 void *pvHdr, size_t cbHdr, const void *pvPayload, size_t cbPayload) 259 { 260 int rc = audioTestSvcClientSend(pClient, pvHdr, cbHdr); 261 if ( RT_SUCCESS(rc) 262 && cbPayload) 263 { 264 rc = audioTestSvcClientSend(pClient, (uint8_t *)pvPayload, cbPayload); 265 } 266 267 return rc; 165 */ 166 static int audioTestSvcClientSendMsg(PATSCLIENT pClient, void *pvHdr, size_t cbHdr) 167 { 168 RT_NOREF(cbHdr); 169 AssertPtrReturn(pClient->pTransport, VERR_WRONG_ORDER); 170 AssertPtrReturn(pClient->pTransportInst, VERR_WRONG_ORDER); 171 AssertPtrReturn(pClient->pTransportClient, VERR_NET_NOT_CONNECTED); 172 return pClient->pTransport->pfnSendPkt(pClient->pTransportInst, pClient->pTransportClient, (PCATSPKTHDR)pvHdr); 268 173 } 269 174 … … 304 209 audioTestSvcClientReqHdrInit(&Req, sizeof(Req), "ACK ", 0); 305 210 306 return audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req) , NULL, 0);211 return audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req)); 307 212 } 308 213 … … 318 223 Req.uVersion = ATS_PROTOCOL_VS; 319 224 audioTestSvcClientReqHdrInit(&Req.Hdr, sizeof(Req), ATSPKT_OPCODE_HOWDY, 0); 320 int rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req) , NULL, 0);225 int rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req)); 321 226 if (RT_SUCCESS(rc)) 322 227 rc = audioTestSvcClientRecvAck(pClient); … … 325 230 326 231 /** 327 * Sends a disconnect command to an ATS server. 328 * 329 * @returns VBox status code. 330 * @param pClient Client to send command for. 331 */ 332 static int audioTestSvcClientDoBye(PATSCLIENT pClient) 333 { 334 ATSPKTHDR Hdr; 335 audioTestSvcClientReqHdrInit(&Hdr, sizeof(Hdr), ATSPKT_OPCODE_BYE, 0); 336 int rc = audioTestSvcClientSendMsg(pClient, &Hdr, sizeof(Hdr), NULL, 0); 337 if (RT_SUCCESS(rc)) 338 rc = audioTestSvcClientRecvAck(pClient); 339 340 return rc; 341 } 342 343 /** 344 * Connects to an ATS server. 232 * Creates an ATS client. 233 * 234 * @returns VBox status code. 235 * @param pClient Client to create. 236 */ 237 int AudioTestSvcClientCreate(PATSCLIENT pClient) 238 { 239 audioTestSvcClientInit(pClient); 240 241 /* 242 * The default transporter is the first one. 243 */ 244 pClient->pTransport = g_apTransports[0]; /** @todo Make this dynamic. */ 245 246 return pClient->pTransport->pfnCreate(&pClient->pTransportInst); 247 } 248 249 /** 250 * Destroys an ATS client. 251 * 252 * @returns VBox status code. 253 * @param pClient Client to destroy. 254 */ 255 void AudioTestSvcClientDestroy(PATSCLIENT pClient) 256 { 257 if (pClient->pTransport) 258 pClient->pTransport->pfnTerm(pClient->pTransportInst); 259 } 260 261 /** 262 * Handles a command line option. 263 * 264 * @returns VBox status code. 265 * @param pClient Client to handle option for. 266 * @param ch Option (short) to handle. 267 * @param pVal Option union to store the result in on success. 268 */ 269 int AudioTestSvcClientHandleOption(PATSCLIENT pClient, int ch, PCRTGETOPTUNION pVal) 270 { 271 AssertPtrReturn(pClient->pTransport, VERR_WRONG_ORDER); /* Must be created first via AudioTestSvcClientCreate(). */ 272 if (!pClient->pTransport->pfnOption) 273 return VERR_GETOPT_UNKNOWN_OPTION; 274 return pClient->pTransport->pfnOption(pClient->pTransportInst, ch, pVal); 275 } 276 277 /** 278 * Connects to an ATS peer. 345 279 * 346 280 * @returns VBox status code. 347 281 * @param pClient Client to connect. 348 * @param pszAddr Address to connect to. If NULL, 127.0.0.1 (localhost) will be used. 349 * @param uPort Port to connect. If set to 0, port 6052 (ATS_DEFAULT_PORT) will be used. 350 */ 351 int AudioTestSvcClientConnect(PATSCLIENT pClient, const char *pszAddr, uint32_t uPort) 352 { 353 audioTestSvcClientInit(pClient); 354 355 int rc = RTTcpClientConnect(pszAddr ? pszAddr : ATS_TCP_HOST_DEFAULT_ADDR_STR, uPort == 0 ? ATS_TCP_HOST_DEFAULT_PORT : uPort, &pClient->hSock); 282 */ 283 int AudioTestSvcClientConnect(PATSCLIENT pClient) 284 { 285 int rc = pClient->pTransport->pfnStart(pClient->pTransportInst); 356 286 if (RT_SUCCESS(rc)) 357 287 { 358 rc = audioTestSvcClientDoGreet(pClient); 288 rc = pClient->pTransport->pfnWaitForConnect(pClient->pTransportInst, &pClient->pTransportClient); 289 if (RT_SUCCESS(rc)) 290 { 291 rc = audioTestSvcClientDoGreet(pClient); 292 } 359 293 } 360 294 … … 378 312 audioTestSvcClientReqHdrInit(&Req.Hdr, sizeof(Req), ATSPKT_OPCODE_TESTSET_BEGIN, 0); 379 313 380 rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req) , NULL, 0);314 rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req)); 381 315 if (RT_SUCCESS(rc)) 382 316 rc = audioTestSvcClientRecvAck(pClient); … … 401 335 audioTestSvcClientReqHdrInit(&Req.Hdr, sizeof(Req), ATSPKT_OPCODE_TESTSET_END, 0); 402 336 403 rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req) , NULL, 0);337 rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req)); 404 338 if (RT_SUCCESS(rc)) 405 339 rc = audioTestSvcClientRecvAck(pClient); … … 424 358 audioTestSvcClientReqHdrInit(&Req.Hdr, sizeof(Req), ATSPKT_OPCODE_TONE_PLAY, 0); 425 359 426 int rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req) , NULL, 0);360 int rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req)); 427 361 if (RT_SUCCESS(rc)) 428 362 rc = audioTestSvcClientRecvAck(pClient); … … 447 381 audioTestSvcClientReqHdrInit(&Req.Hdr, sizeof(Req), ATSPKT_OPCODE_TONE_RECORD, 0); 448 382 449 int rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req) , NULL, 0);383 int rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req)); 450 384 if (RT_SUCCESS(rc)) 451 385 rc = audioTestSvcClientRecvAck(pClient); … … 476 410 AssertRCReturn(rc, rc); 477 411 478 rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req) , NULL, 0);412 rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req)); 479 413 while (RT_SUCCESS(rc)) 480 414 { 481 415 ATSSRVREPLY Reply; 482 416 RT_ZERO(Reply); 417 483 418 rc = audioTestSvcClientRecvReply(pClient, &Reply, false /* fNoDataOk */); 484 419 if (RT_SUCCESS(rc)) 485 420 { 486 /* Calculate and validate checksum. */ 487 uint32_t uDataCrc32; 488 memcpy(&uDataCrc32, Reply.pvPayload, sizeof(uint32_t)); 489 490 if ( uDataCrc32 491 && uDataCrc32 != RTCrc32((uint8_t *)Reply.pvPayload + 4, Reply.cbPayload - 4)) 492 rc = VERR_TAR_CHKSUM_MISMATCH; /** @todo Fudge! */ 421 /* Extract received CRC32 checksum. */ 422 const size_t cbCrc32 = sizeof(uint32_t); /* Skip CRC32 in payload for actual CRC verification. */ 423 424 uint32_t uSrcCrc32; 425 memcpy(&uSrcCrc32, Reply.pvPayload, cbCrc32); 426 427 if (uSrcCrc32) 428 { 429 const uint32_t uDstCrc32 = RTCrc32((uint8_t *)Reply.pvPayload + cbCrc32, Reply.cbPayload - cbCrc32); 430 431 Log2Func(("uSrcCrc32=%#x, cbRead=%zu -> uDstCrc32=%#x\n" 432 "%.*Rhxd\n", 433 uSrcCrc32, Reply.cbPayload - cbCrc32, uDstCrc32, 434 RT_MIN(64, Reply.cbPayload - cbCrc32), (uint8_t *)Reply.pvPayload + cbCrc32)); 435 436 if (uSrcCrc32 != uDstCrc32) 437 rc = VERR_TAR_CHKSUM_MISMATCH; /** @todo Fudge! */ 438 } 493 439 494 440 if (RT_SUCCESS(rc)) … … 498 444 && Reply.cbPayload) 499 445 { 500 rc = RTFileWrite(hFile, (uint8_t *)Reply.pvPayload + 4, Reply.cbPayload - 4, NULL);446 rc = RTFileWrite(hFile, (uint8_t *)Reply.pvPayload + cbCrc32, Reply.cbPayload - cbCrc32, NULL); 501 447 } 502 448 else if (RTStrNCmp(Reply.szOp, "DATA EOF", ATSPKT_OPCODE_MAX_LEN) == 0) … … 537 483 int AudioTestSvcClientClose(PATSCLIENT pClient) 538 484 { 539 int rc = audioTestSvcClientDoBye(pClient); 540 if (RT_SUCCESS(rc)) 541 rc = RTTcpClientClose(pClient->hSock); 542 543 return rc; 544 } 545 485 pClient->pTransport->pfnNotifyBye(pClient->pTransportInst, pClient->pTransportClient); 486 487 return VINF_SUCCESS; 488 } 489 -
trunk/src/VBox/Devices/Audio/AudioTestServiceClient.h
r89614 r89962 22 22 #endif 23 23 24 #include "AudioTestServiceInternal.h" 25 26 /** 27 * Structure for maintaining an ATS client. 28 */ 24 29 typedef struct ATSCLIENT 25 30 { 26 uint8_t abHdr[16]; 27 uint16_t cbHdr; 28 RTSOCKET hSock; 31 /** Pointer to the selected transport layer. */ 32 PCATSTRANSPORT pTransport; 33 /** Pointer to the selected transport instance to use. */ 34 PATSTRANSPORTINST pTransportInst; 35 /** The opaque client instance. */ 36 PATSTRANSPORTCLIENT pTransportClient; 29 37 } ATSCLIENT; 38 /** Pointer to an ATS client. */ 30 39 typedef ATSCLIENT *PATSCLIENT; 31 40 32 int AudioTestSvcClientConnect(PATSCLIENT pClient, const char *pszAddr, uint32_t uPort); 41 int AudioTestSvcClientCreate(PATSCLIENT pClient); 42 void AudioTestSvcClientDestroy(PATSCLIENT pClient); 43 int AudioTestSvcClientConnect(PATSCLIENT pClient); 44 int AudioTestSvcClientHandleOption(PATSCLIENT pClient, int ch, PCRTGETOPTUNION pVal); 33 45 int AudioTestSvcClientTestSetBegin(PATSCLIENT pClient, const char *pszTag); 34 46 int AudioTestSvcClientTestSetEnd(PATSCLIENT pClient, const char *pszTag); -
trunk/src/VBox/Devices/Audio/AudioTestServiceInternal.h
r89541 r89962 46 46 /** The description. */ 47 47 const char *pszDesc; 48 49 /** 50 * Initializes the transport layer. 48 /** Pointer to an array of options. */ 49 PCRTGETOPTDEF paOpts; 50 /** The number of options in the array. */ 51 size_t cOpts; 52 53 /** 54 * Print the usage information for this transport layer. 55 * 56 * @param pStream The stream to print the usage info to. 57 * 58 * @remarks This is only required if TXSTRANSPORT::cOpts is greater than 0. 59 */ 60 DECLR3CALLBACKMEMBER(void, pfnUsage,(PRTSTREAM pStream)); 61 62 /** 63 * Creates a transport instance. 51 64 * 52 65 * @returns IPRT status code. On errors, the transport layer shall call 53 66 * RTMsgError to display the error details to the user. 54 * @param pThis The transport instance. 55 * @param pszBindAddr Bind address. Empty means any address. 56 * @param uBindPort Bind port. If set to 0, ATS_DEFAULT_PORT is being used. 57 */ 58 DECLR3CALLBACKMEMBER(int, pfnInit, (PATSTRANSPORTINST pThis, const char *pszBindAddr, uint32_t uBindPort)); 59 60 /** 61 * Terminate the transport layer, closing and freeing resources. 67 * @param ppThis Where to return the created transport instance on success. 68 */ 69 DECLR3CALLBACKMEMBER(int, pfnCreate, (PPATSTRANSPORTINST ppThis)); 70 71 /** 72 * Destroys a transport instance. 73 * 74 * On errors, the transport layer shall call RTMsgError to display the error 75 * details to the user. 76 * 77 * @returns IPRT status code. On errors, the transport layer shall call 78 * RTMsgError to display the error details to the user. 79 * @param pThis The transport instance. 80 * The pointer will be invalid on return. 81 */ 82 DECLR3CALLBACKMEMBER(int, pfnDestroy, (PATSTRANSPORTINST pThis)); 83 84 /** 85 * Handle an option. 86 * 87 * When encountering an options that is not part of the base options, we'll call 88 * this method for each transport layer until one handles it. 89 * 90 * @retval VINF_SUCCESS if handled. 91 * @retval VERR_TRY_AGAIN if not handled. 92 * @retval VERR_INVALID_PARAMETER if we should exit with a non-zero status. 93 * 94 * @param pThis Transport instance to set options for. 95 * @param ch The short option value. 96 * @param pVal Pointer to the value union. 97 * 98 * @remarks This is only required if TXSTRANSPORT::cOpts is greater than 0. 99 */ 100 DECLR3CALLBACKMEMBER(int, pfnOption,(PATSTRANSPORTINST pThis, int ch, PCRTGETOPTUNION pVal)); 101 102 /** 103 * Starts a transport instance. 104 * 105 * @returns IPRT status code. On errors, the transport layer shall call 106 * RTMsgError to display the error details to the user. 107 * @param pThis Transport instance to initialize. 108 */ 109 DECLR3CALLBACKMEMBER(int, pfnStart, (PATSTRANSPORTINST pThis)); 110 111 /** 112 * Terminate a transport instance, closing and freeing resources. 62 113 * 63 114 * On errors, the transport layer shall call RTMsgError to display the error -
trunk/src/VBox/Devices/Audio/AudioTestServiceTcp.cpp
r89614 r89962 20 20 * Header Files * 21 21 *********************************************************************************************************************************/ 22 #define LOG_GROUP RTLOGGROUP_DEFAULT22 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO /** @todo Add an own log group for this? */ 23 23 #include <iprt/asm.h> 24 24 #include <iprt/assert.h> … … 34 34 #include <iprt/time.h> 35 35 36 #include <VBox/log.h> 37 36 38 #include "AudioTestService.h" 37 39 #include "AudioTestServiceInternal.h" … … 46 48 * Structures and Typedefs * 47 49 *********************************************************************************************************************************/ 48 49 50 /** 50 51 * TCP specific client data. … … 53 54 { 54 55 /** Socket of the current client. */ 55 RTSOCKET hTcpClient; 56 RTSOCKET hTcpClient; 57 /** Indicates whether \a hTcpClient comes from the server or from a client 58 * connect (relevant when closing it). */ 59 bool fFromServer; 56 60 /** The size of the stashed data. */ 57 size_t cbTcpStashed;61 size_t cbTcpStashed; 58 62 /** The size of the stashed data allocation. */ 59 size_t cbTcpStashedAlloced;63 size_t cbTcpStashedAlloced; 60 64 /** The stashed data. */ 61 uint8_t *pbTcpStashed;65 uint8_t *pbTcpStashed; 62 66 } ATSTRANSPORTCLIENT; 67 68 /** 69 * Enumeration for the TCP/IP connection mode. 70 */ 71 typedef enum ATSTCPMODE 72 { 73 /** Both: Uses parallel client and server connection methods (via threads). */ 74 ATSTCPMODE_BOTH = 0, 75 /** Client only: Connects to a server. */ 76 ATSTCPMODE_CLIENT, 77 /** Server only: Listens for new incoming client connections. */ 78 ATSTCPMODE_SERVER 79 } ATSTCPMODE; 80 81 /** 82 * Structure for keeping Audio Test Service (ATS) transport instance-specific data. 83 */ 84 typedef struct ATSTRANSPORTINST 85 { 86 /** Critical section for serializing access. */ 87 RTCRITSECT CritSect; 88 /** Connection mode to use. */ 89 ATSTCPMODE enmMode; 90 /** The addresses to bind to. Empty string means any. */ 91 char szBindAddr[256]; 92 /** The TCP port to listen to. */ 93 uint32_t uBindPort; 94 /** The addresses to connect to if running in reversed (VM NATed) mode. */ 95 char szConnectAddr[256]; 96 /** The TCP port to connect to if running in reversed (VM NATed) mode. */ 97 uint32_t uConnectPort; 98 /** Pointer to the TCP server instance. */ 99 PRTTCPSERVER pTcpServer; 100 /** Thread calling RTTcpServerListen2. */ 101 RTTHREAD hThreadServer; 102 /** Thread calling RTTcpClientConnect. */ 103 RTTHREAD hThreadConnect; 104 /** The main thread handle (for signalling). */ 105 RTTHREAD hThreadMain; 106 /** Stop connecting attempts when set. */ 107 bool fStopConnecting; 108 /** Connect cancel cookie. */ 109 PRTTCPCLIENTCONNECTCANCEL volatile pConnectCancelCookie; 110 } ATSTRANSPORTINST; 111 /** Pointer to an Audio Test Service (ATS) TCP/IP transport instance. */ 112 typedef ATSTRANSPORTINST *PATSTRANSPORTINST; 113 114 /** 115 * Structure holding an ATS connection context, which is 116 * required when connecting a client via server (listening) or client (connecting). 117 */ 118 typedef struct ATSCONNCTX 119 { 120 /** Pointer to transport instance to use. */ 121 PATSTRANSPORTINST pInst; 122 /** Pointer to transport client to connect. */ 123 PATSTRANSPORTCLIENT pClient; 124 } ATSCONNCTX; 125 /** Pointer to an Audio Test Service (ATS) TCP/IP connection context. */ 126 typedef ATSCONNCTX *PATSCONNCTX; 63 127 64 128 … … 76 140 if (pClient->hTcpClient != NIL_RTSOCKET) 77 141 { 78 int rc = RTTcpServerDisconnectClient2(pClient->hTcpClient); 142 int rc; 143 if (pClient->fFromServer) 144 rc = RTTcpServerDisconnectClient2(pClient->hTcpClient); 145 else 146 rc = RTTcpClientClose(pClient->hTcpClient); 79 147 pClient->hTcpClient = NIL_RTSOCKET; 80 148 AssertRCSuccess(rc); … … 89 157 90 158 /** 159 * Sets the current client socket in a safe manner. 160 * 161 * @returns NIL_RTSOCKET if consumed, other wise hTcpClient. 162 * @param pThis Transport instance. 163 * @param pClient Client to set the socket for. 164 * @param fFromServer Whether the socket is from a server (listening) or client (connecting) call. 165 * Important when closing / disconnecting. 166 * @param hTcpClient The client socket. 167 */ 168 static RTSOCKET atsTcpSetClient(PATSTRANSPORTINST pThis, PATSTRANSPORTCLIENT pClient, bool fFromServer, RTSOCKET hTcpClient) 169 { 170 RTCritSectEnter(&pThis->CritSect); 171 if ( pClient->hTcpClient == NIL_RTSOCKET 172 && !pThis->fStopConnecting) 173 { 174 LogFunc(("New client connected\n")); 175 176 pClient->fFromServer = fFromServer; 177 pClient->hTcpClient = hTcpClient; 178 hTcpClient = NIL_RTSOCKET; /* Invalidate, as pClient has now ownership. */ 179 } 180 RTCritSectLeave(&pThis->CritSect); 181 return hTcpClient; 182 } 183 184 /** 185 * Checks if it's a fatal RTTcpClientConnect return code. 186 * 187 * @returns true / false. 188 * @param rc The IPRT status code. 189 */ 190 static bool atsTcpIsFatalClientConnectStatus(int rc) 191 { 192 return rc != VERR_NET_UNREACHABLE 193 && rc != VERR_NET_HOST_DOWN 194 && rc != VERR_NET_HOST_UNREACHABLE 195 && rc != VERR_NET_CONNECTION_REFUSED 196 && rc != VERR_TIMEOUT 197 && rc != VERR_NET_CONNECTION_TIMED_OUT; 198 } 199 200 /** 201 * Server mode connection thread. 202 * 203 * @returns iprt status code. 204 * @param hSelf Thread handle. Ignored. 205 * @param pvUser Pointer to ATSTRANSPORTINST the thread is bound to. 206 */ 207 static DECLCALLBACK(int) atsTcpServerConnectThread(RTTHREAD hSelf, void *pvUser) 208 { 209 RT_NOREF(hSelf); 210 211 PATSCONNCTX pConnCtx = (PATSCONNCTX)pvUser; 212 PATSTRANSPORTINST pThis = pConnCtx->pInst; 213 PATSTRANSPORTCLIENT pClient = pConnCtx->pClient; 214 215 RTSOCKET hTcpClient; 216 int rc = RTTcpServerListen2(pThis->pTcpServer, &hTcpClient); 217 if (RT_SUCCESS(rc)) 218 { 219 hTcpClient = atsTcpSetClient(pThis, pClient, true /* fFromServer */, hTcpClient); 220 RTTcpServerDisconnectClient2(hTcpClient); 221 } 222 223 return rc; 224 } 225 226 /** 227 * Client mode connection thread. 228 * 229 * @returns iprt status code. 230 * @param hSelf Thread handle. Use to sleep on. The main thread will 231 * signal it to speed up thread shutdown. 232 * @param pvUser Pointer to a connection context (PATSCONNCTX) the thread is bound to. 233 */ 234 static DECLCALLBACK(int) atsTcpClientConnectThread(RTTHREAD hSelf, void *pvUser) 235 { 236 PATSCONNCTX pConnCtx = (PATSCONNCTX)pvUser; 237 PATSTRANSPORTINST pThis = pConnCtx->pInst; 238 PATSTRANSPORTCLIENT pClient = pConnCtx->pClient; 239 240 for (;;) 241 { 242 /* Stop? */ 243 RTCritSectEnter(&pThis->CritSect); 244 bool fStop = pThis->fStopConnecting; 245 RTCritSectLeave(&pThis->CritSect); 246 if (fStop) 247 return VINF_SUCCESS; 248 249 /* Try connect. */ /** @todo make cancelable! */ 250 RTSOCKET hTcpClient; 251 int rc = RTTcpClientConnectEx(pThis->szConnectAddr, pThis->uConnectPort, &hTcpClient, 252 RT_SOCKETCONNECT_DEFAULT_WAIT, &pThis->pConnectCancelCookie); 253 if (RT_SUCCESS(rc)) 254 { 255 hTcpClient = atsTcpSetClient(pThis, pClient, false /* fFromServer */, hTcpClient); 256 RTTcpClientCloseEx(hTcpClient, true /* fGracefulShutdown*/); 257 break; 258 } 259 260 if (atsTcpIsFatalClientConnectStatus(rc)) 261 return rc; 262 263 /* Delay a wee bit before retrying. */ 264 RTThreadUserWait(hSelf, 1536); 265 } 266 return VINF_SUCCESS; 267 } 268 269 /** 270 * Wait on the threads to complete. 271 * 272 * @returns Thread status (if collected), otherwise VINF_SUCCESS. 273 * @param pThis Transport instance. 274 * @param cMillies The period to wait on each thread. 275 */ 276 static int atsTcpConnectWaitOnThreads(PATSTRANSPORTINST pThis, RTMSINTERVAL cMillies) 277 { 278 int rcRet = VINF_SUCCESS; 279 280 if (pThis->hThreadConnect != NIL_RTTHREAD) 281 { 282 int rcThread; 283 int rc2 = RTThreadWait(pThis->hThreadConnect, cMillies, &rcThread); 284 if (RT_SUCCESS(rc2)) 285 { 286 pThis->hThreadConnect = NIL_RTTHREAD; 287 rcRet = rcThread; 288 } 289 } 290 291 if (pThis->hThreadServer != NIL_RTTHREAD) 292 { 293 int rcThread; 294 int rc2 = RTThreadWait(pThis->hThreadServer, cMillies, &rcThread); 295 if (RT_SUCCESS(rc2)) 296 { 297 pThis->hThreadServer = NIL_RTTHREAD; 298 if (RT_SUCCESS(rc2)) 299 rcRet = rcThread; 300 } 301 } 302 return rcRet; 303 } 304 305 /** 91 306 * @interface_method_impl{ATSTRANSPORT,pfnWaitForConnect} 92 307 */ 93 308 static DECLCALLBACK(int) atsTcpWaitForConnect(PATSTRANSPORTINST pThis, PPATSTRANSPORTCLIENT ppClientNew) 94 309 { 310 PATSTRANSPORTCLIENT pClient = (PATSTRANSPORTCLIENT)RTMemAllocZ(sizeof(ATSTRANSPORTCLIENT)); 311 AssertPtrReturn(pClient, VERR_NO_MEMORY); 312 95 313 int rc; 96 RTSOCKET hClientNew; 97 98 rc = RTTcpServerListen2(pThis->pTcpServer, &hClientNew); 99 Log(("atsTcpWaitForConnect: RTTcpServerListen2 -> %Rrc\n", rc)); 314 315 if (pThis->enmMode == ATSTCPMODE_SERVER) 316 { 317 pClient->fFromServer = true; 318 rc = RTTcpServerListen2(pThis->pTcpServer, &pClient->hTcpClient); 319 LogFunc(("RTTcpServerListen2 -> %Rrc\n", rc)); 320 } 321 else if (pThis->enmMode == ATSTCPMODE_CLIENT) 322 { 323 pClient->fFromServer = false; 324 for (;;) 325 { 326 Log2Func(("Calling RTTcpClientConnect(%s, %u,)...\n", pThis->szConnectAddr, pThis->uConnectPort)); 327 rc = RTTcpClientConnect(pThis->szConnectAddr, pThis->uConnectPort, &pClient->hTcpClient); 328 LogFunc(("RTTcpClientConnect -> %Rrc\n", rc)); 329 if (RT_SUCCESS(rc) || atsTcpIsFatalClientConnectStatus(rc)) 330 break; 331 332 /* Delay a wee bit before retrying. */ 333 RTThreadSleep(1536); 334 } 335 } 336 else 337 { 338 Assert(pThis->enmMode == ATSTCPMODE_BOTH); 339 340 /* 341 * Create client threads. 342 */ 343 RTCritSectEnter(&pThis->CritSect); 344 345 pThis->fStopConnecting = false; 346 RTCritSectLeave(&pThis->CritSect); 347 348 atsTcpConnectWaitOnThreads(pThis, 32 /* cMillies */); 349 350 ATSCONNCTX ConnCtx; 351 RT_ZERO(ConnCtx); 352 ConnCtx.pInst = pThis; 353 ConnCtx.pClient = pClient; 354 355 rc = VINF_SUCCESS; 356 if (pThis->hThreadConnect == NIL_RTTHREAD) 357 { 358 pThis->pConnectCancelCookie = NULL; 359 rc = RTThreadCreate(&pThis->hThreadConnect, atsTcpClientConnectThread, &ConnCtx, 0, RTTHREADTYPE_DEFAULT, 360 RTTHREADFLAGS_WAITABLE, "tcpconn"); 361 } 362 if (pThis->hThreadServer == NIL_RTTHREAD && RT_SUCCESS(rc)) 363 rc = RTThreadCreate(&pThis->hThreadServer, atsTcpServerConnectThread, &ConnCtx, 0, RTTHREADTYPE_DEFAULT, 364 RTTHREADFLAGS_WAITABLE, "tcpserv"); 365 366 RTCritSectEnter(&pThis->CritSect); 367 368 /* 369 * Wait for connection to be established. 370 */ 371 while ( RT_SUCCESS(rc) 372 && pClient->hTcpClient == NIL_RTSOCKET) 373 { 374 RTCritSectLeave(&pThis->CritSect); 375 rc = atsTcpConnectWaitOnThreads(pThis, 10 /* cMillies */); 376 RTCritSectEnter(&pThis->CritSect); 377 } 378 379 /* 380 * Cancel the threads. 381 */ 382 pThis->fStopConnecting = true; 383 384 RTCritSectLeave(&pThis->CritSect); 385 RTTcpClientCancelConnect(&pThis->pConnectCancelCookie); 386 } 100 387 101 388 if (RT_SUCCESS(rc)) 102 389 { 103 PATSTRANSPORTCLIENT pClient = (PATSTRANSPORTCLIENT)RTMemAllocZ(sizeof(ATSTRANSPORTCLIENT)); 104 if (RT_LIKELY(pClient)) 105 { 106 pClient->hTcpClient = hClientNew; 107 pClient->cbTcpStashed = 0; 108 pClient->cbTcpStashedAlloced = 0; 109 pClient->pbTcpStashed = NULL; 110 *ppClientNew = pClient; 111 } 112 else 113 { 114 RTTcpServerDisconnectClient2(hClientNew); 115 rc = VERR_NO_MEMORY; 390 *ppClientNew = pClient; 391 } 392 else 393 { 394 if (pClient) 395 { 396 RTTcpServerDisconnectClient2(pClient->hTcpClient); 397 398 RTMemFree(pClient); 399 pClient = NULL; 116 400 } 117 401 } … … 125 409 static DECLCALLBACK(void) atsTcpNotifyReboot(PATSTRANSPORTINST pThis) 126 410 { 127 Log (("atsTcpNotifyReboot:RTTcpServerDestroy(%p)\n", pThis->pTcpServer));411 LogFunc(("RTTcpServerDestroy(%p)\n", pThis->pTcpServer)); 128 412 if (pThis->pTcpServer) 129 413 { … … 140 424 static DECLCALLBACK(void) atsTcpNotifyBye(PATSTRANSPORTINST pThis, PATSTRANSPORTCLIENT pClient) 141 425 { 142 Log (("atsTcpNotifyBye:atsTcpDisconnectClient %RTsock\n", pClient->hTcpClient));426 LogFunc(("atsTcpDisconnectClient %RTsock\n", pClient->hTcpClient)); 143 427 atsTcpDisconnectClient(pThis, pClient); 144 428 RTMemFree(pClient); … … 171 455 * Disconnect the client. 172 456 */ 173 Log (("atsTcpBabble:atsTcpDisconnectClient(%RTsock) (RTTcpWrite rc=%Rrc)\n", pClient->hTcpClient, rc));457 LogFunc(("atsTcpDisconnectClient(%RTsock) (RTTcpWrite rc=%Rrc)\n", pClient->hTcpClient, rc)); 174 458 atsTcpDisconnectClient(pThis, pClient); 175 459 } … … 180 464 static DECLCALLBACK(int) atsTcpSendPkt(PATSTRANSPORTINST pThis, PATSTRANSPORTCLIENT pClient, PCATSPKTHDR pPktHdr) 181 465 { 182 Assert (pPktHdr->cb >= sizeof(ATSPKTHDR));466 AssertReturn(pPktHdr->cb >= sizeof(ATSPKTHDR), VERR_INVALID_PARAMETER); 183 467 184 468 /* … … 186 470 */ 187 471 size_t cbToSend = RT_ALIGN_Z(pPktHdr->cb, ATSPKT_ALIGNMENT); 188 LogFlowFunc(("%RU32 -> %zu\n", pPktHdr->cb, cbToSend)); 472 473 Log3Func(("%RU32 -> %zu\n", pPktHdr->cb, cbToSend)); 474 475 Log3Func(("Header:\n" 476 "%.*Rhxd\n", RT_MIN(sizeof(ATSPKTHDR), cbToSend), pPktHdr)); 477 478 if (cbToSend > sizeof(ATSPKTHDR)) 479 Log3Func(("Payload:\n" 480 "%.*Rhxd\n", 481 RT_MIN(64, cbToSend - sizeof(ATSPKTHDR)), (uint8_t *)pPktHdr + sizeof(ATSPKTHDR))); 482 189 483 int rc = RTTcpWrite(pClient->hTcpClient, pPktHdr, cbToSend); 190 484 if ( RT_FAILURE(rc) … … 192 486 { 193 487 /* assume fatal connection error. */ 194 Log (("RTTcpWrite -> %Rrc -> atsTcpDisconnectClient(%RTsock)\n", rc, pClient->hTcpClient));488 LogFunc(("RTTcpWrite -> %Rrc -> atsTcpDisconnectClient(%RTsock)\n", rc, pClient->hTcpClient)); 195 489 atsTcpDisconnectClient(pThis, pClient); 196 490 } … … 237 531 238 532 /* 239 * Read and valid the length.533 * Read and validate the length. 240 534 */ 241 535 while (offData < sizeof(uint32_t)) … … 247 541 if (cbRead == 0) 248 542 { 249 Log (("atsTcpRecvPkt:RTTcpRead -> %Rrc / cbRead=0 -> VERR_NET_NOT_CONNECTED (#1)\n", rc));543 LogFunc(("RTTcpRead -> %Rrc / cbRead=0 -> VERR_NET_NOT_CONNECTED (#1)\n", rc)); 250 544 rc = VERR_NET_NOT_CONNECTED; 251 545 break; … … 287 581 if (cbRead == 0) 288 582 { 289 Log (("atsTcpRecvPkt:RTTcpRead -> %Rrc / cbRead=0 -> VERR_NET_NOT_CONNECTED (#2)\n", rc));583 LogFunc(("RTTcpRead -> %Rrc / cbRead=0 -> VERR_NET_NOT_CONNECTED (#2)\n", rc)); 290 584 rc = VERR_NET_NOT_CONNECTED; 291 585 break; 292 586 } 587 293 588 offData += cbRead; 294 589 } 590 591 Log3Func(("Header:\n" 592 "%.*Rhxd\n", sizeof(ATSPKTHDR), pbData)); 593 594 if ( RT_SUCCESS(rc) 595 && cbData > sizeof(ATSPKTHDR)) 596 Log3Func(("Payload:\n" 597 "%.*Rhxd\n", RT_MIN(64, cbData - sizeof(ATSPKTHDR)), (uint8_t *)pbData + sizeof(ATSPKTHDR))); 295 598 } 296 599 } … … 317 620 318 621 /* assume fatal connection error. */ 319 Log (("atsTcpRecvPkt:RTTcpRead -> %Rrc -> atsTcpDisconnectClient(%RTsock)\n", rc, pClient->hTcpClient));622 LogFunc(("RTTcpRead -> %Rrc -> atsTcpDisconnectClient(%RTsock)\n", rc, pClient->hTcpClient)); 320 623 atsTcpDisconnectClient(pThis, pClient); 321 624 } … … 358 661 static DECLCALLBACK(void) atsTcpTerm(PATSTRANSPORTINST pThis) 359 662 { 663 /* Signal thread */ 664 if (RTCritSectIsInitialized(&pThis->CritSect)) 665 { 666 RTCritSectEnter(&pThis->CritSect); 667 pThis->fStopConnecting = true; 668 RTCritSectLeave(&pThis->CritSect); 669 } 670 671 if (pThis->hThreadConnect != NIL_RTTHREAD) 672 { 673 RTThreadUserSignal(pThis->hThreadConnect); 674 RTTcpClientCancelConnect(&pThis->pConnectCancelCookie); 675 } 676 360 677 /* Shut down the server (will wake up thread). */ 361 678 if (pThis->pTcpServer) 362 679 { 363 Log (("atsTcpTerm:Destroying server...\n"));680 LogFunc(("Destroying server...\n")); 364 681 int rc = RTTcpServerDestroy(pThis->pTcpServer); 365 682 if (RT_FAILURE(rc)) … … 368 685 } 369 686 370 Log(("atsTcpTerm: done\n")); 371 } 372 373 /** 374 * @interface_method_impl{ATSTRANSPORT,pfnInit} 375 */ 376 static DECLCALLBACK(int) atsTcpInit(PATSTRANSPORTINST pThis, const char *pszBindAddr, uint32_t uBindPort) 377 { 378 int rc = RTTcpServerCreateEx(pszBindAddr[0] ? pszBindAddr : NULL, uBindPort, &pThis->pTcpServer); 379 if (RT_FAILURE(rc)) 380 { 381 if (rc == VERR_NET_DOWN) 382 { 383 RTMsgInfo("RTTcpServerCreateEx(%s, %u,) failed: %Rrc, retrying for 20 seconds...\n", 384 pszBindAddr[0] ? pszBindAddr : NULL, uBindPort, rc); 385 uint64_t StartMs = RTTimeMilliTS(); 386 do 687 /* Wait for the thread (they should've had some time to quit by now). */ 688 atsTcpConnectWaitOnThreads(pThis, 15000); 689 690 /* Finally, clean up the critical section. */ 691 if (RTCritSectIsInitialized(&pThis->CritSect)) 692 RTCritSectDelete(&pThis->CritSect); 693 694 LogFunc(("Done\n")); 695 } 696 697 /** 698 * @interface_method_impl{ATSTRANSPORT,pfnCreate} 699 */ 700 static DECLCALLBACK(int) atsTcpCreate(PATSTRANSPORTINST *ppThis) 701 { 702 PATSTRANSPORTINST pThis = (PATSTRANSPORTINST)RTMemAllocZ(sizeof(ATSTRANSPORTINST)); 703 AssertPtrReturn(pThis, VERR_NO_MEMORY); 704 705 *ppThis = pThis; 706 return VINF_SUCCESS; 707 } 708 709 /** 710 * @interface_method_impl{ATSTRANSPORT,pfnDestroy} 711 */ 712 static DECLCALLBACK(int) atsTcpDestroy(PATSTRANSPORTINST pThis) 713 { 714 /** @todo Anything else to do here? */ 715 RTMemFree(pThis); 716 717 return VINF_SUCCESS; 718 } 719 720 /** 721 * @interface_method_impl{ATSTRANSPORT,pfnStart} 722 */ 723 static DECLCALLBACK(int) atsTcpStart(PATSTRANSPORTINST pThis) 724 { 725 int rc = RTCritSectInit(&pThis->CritSect); 726 if (RT_SUCCESS(rc) && pThis->enmMode != ATSTCPMODE_CLIENT) 727 { 728 rc = RTTcpServerCreateEx(pThis->szBindAddr[0] ? pThis->szBindAddr : NULL, pThis->uBindPort, &pThis->pTcpServer); 729 if (RT_FAILURE(rc)) 730 { 731 if (rc == VERR_NET_DOWN) 387 732 { 388 RTThreadSleep(1000); 389 rc = RTTcpServerCreateEx(pszBindAddr[0] ? pszBindAddr : NULL, uBindPort, &pThis->pTcpServer); 390 } while ( rc == VERR_NET_DOWN 391 && RTTimeMilliTS() - StartMs < 20000); 392 if (RT_SUCCESS(rc)) 393 RTMsgInfo("RTTcpServerCreateEx succceeded.\n"); 394 } 395 if (RT_FAILURE(rc)) 396 { 397 pThis->pTcpServer = NULL; 398 RTMsgError("RTTcpServerCreateEx(%s, %u,) failed: %Rrc\n", 399 pszBindAddr[0] ? pszBindAddr : NULL, uBindPort, rc); 733 RTMsgInfo("RTTcpServerCreateEx(%s, %u,) failed: %Rrc, retrying for 20 seconds...\n", 734 pThis->szBindAddr[0] ? pThis->szBindAddr : NULL, pThis->uBindPort, rc); 735 uint64_t StartMs = RTTimeMilliTS(); 736 do 737 { 738 RTThreadSleep(1000); 739 rc = RTTcpServerCreateEx(pThis->szBindAddr[0] ? pThis->szBindAddr : NULL, pThis->uBindPort, &pThis->pTcpServer); 740 } while ( rc == VERR_NET_DOWN 741 && RTTimeMilliTS() - StartMs < 20000); 742 if (RT_SUCCESS(rc)) 743 RTMsgInfo("RTTcpServerCreateEx succceeded.\n"); 744 } 745 746 if (RT_FAILURE(rc)) 747 { 748 RTMsgError("RTTcpServerCreateEx(%s, %u,) failed: %Rrc\n", 749 pThis->szBindAddr[0] ? pThis->szBindAddr : NULL, pThis->uBindPort, rc); 750 } 400 751 } 401 752 } … … 403 754 return rc; 404 755 } 756 757 /** 758 * @interface_method_impl{ATSTRANSPORT,pfnOption} 759 */ 760 static DECLCALLBACK(int) atsTcpOption(PATSTRANSPORTINST pThis, int ch, PCRTGETOPTUNION pVal) 761 { 762 int rc; 763 764 switch (ch) 765 { 766 case ATSTCPOPT_MODE: 767 if (!strcmp(pVal->psz, "both")) 768 pThis->enmMode = ATSTCPMODE_BOTH; 769 else if (!strcmp(pVal->psz, "client")) 770 pThis->enmMode = ATSTCPMODE_CLIENT; 771 else if (!strcmp(pVal->psz, "server")) 772 pThis->enmMode = ATSTCPMODE_SERVER; 773 else 774 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "Invalid TCP mode: '%s'\n", pVal->psz); 775 return VINF_SUCCESS; 776 777 case ATSTCPOPT_BIND_ADDRESS: 778 rc = RTStrCopy(pThis->szBindAddr, sizeof(pThis->szBindAddr), pVal->psz); 779 if (RT_FAILURE(rc)) 780 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "TCP bind address is too long (%Rrc)", rc); 781 return VINF_SUCCESS; 782 783 case ATSTCPOPT_BIND_PORT: 784 pThis->uBindPort = pVal->u16 == 0 ? ATS_TCP_DEF_BIND_PORT_GUEST : pVal->u16; 785 return VINF_SUCCESS; 786 787 case ATSTCPOPT_CONNECT_ADDRESS: 788 rc = RTStrCopy(pThis->szConnectAddr, sizeof(pThis->szConnectAddr), pVal->psz); 789 if (RT_FAILURE(rc)) 790 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "TCP connect address is too long (%Rrc)", rc); 791 if (!pThis->szConnectAddr[0]) 792 strcpy(pThis->szConnectAddr, ATS_TCP_DEF_CONNECT_GUEST_STR); 793 return VINF_SUCCESS; 794 795 case ATSTCPOPT_CONNECT_PORT: 796 pThis->uConnectPort = pVal->u16 == 0 ? ATS_TCP_DEF_BIND_PORT_GUEST : pVal->u16; 797 return VINF_SUCCESS; 798 799 default: 800 break; 801 } 802 return VERR_TRY_AGAIN; 803 } 804 805 /** 806 * @interface_method_impl{ATSTRANSPORT,pfnUsage} 807 */ 808 DECLCALLBACK(void) atsTcpUsage(PRTSTREAM pStream) 809 { 810 RTStrmPrintf(pStream, 811 " --tcp-mode <both|client|server>\n" 812 " Selects the mode of operation.\n" 813 " Default: both\n" 814 " --tcp-bind-address <address>\n" 815 " The address(es) to listen to TCP connection on. Empty string\n" 816 " means any address, this is the default.\n" 817 " --tcp-bind-port <port>\n" 818 " The port to listen to TCP connections on.\n" 819 " Default: %u\n" 820 " --tcp-connect-address <address>\n" 821 " The address of the server to try connect to in client mode.\n" 822 " Default: " ATS_TCP_DEF_CONNECT_GUEST_STR "\n" 823 " --tcp-connect-port <port>\n" 824 " The port on the server to connect to in client mode.\n" 825 " Default: %u\n" 826 , ATS_TCP_DEF_BIND_PORT_GUEST, ATS_TCP_DEF_CONNECT_PORT_GUEST); 827 } 828 829 /** Command line options for the TCP/IP transport layer. */ 830 static const RTGETOPTDEF g_TcpOpts[] = 831 { 832 { "--tcp-mode", ATSTCPOPT_MODE, RTGETOPT_REQ_STRING }, 833 { "--tcp-bind-address", ATSTCPOPT_BIND_ADDRESS, RTGETOPT_REQ_STRING }, 834 { "--tcp-bind-port", ATSTCPOPT_BIND_PORT, RTGETOPT_REQ_UINT16 }, 835 { "--tcp-connect-address", ATSTCPOPT_CONNECT_ADDRESS, RTGETOPT_REQ_STRING }, 836 { "--tcp-connect-port", ATSTCPOPT_CONNECT_PORT, RTGETOPT_REQ_UINT16 } 837 }; 405 838 406 839 /** TCP/IP transport layer. */ … … 409 842 /* .szName = */ "tcp", 410 843 /* .pszDesc = */ "TCP/IP", 411 /* .pfnInit = */ atsTcpInit, 844 /* .cOpts = */ &g_TcpOpts[0], 845 /* .paOpts = */ RT_ELEMENTS(g_TcpOpts), 846 /* .pfnUsage = */ atsTcpUsage, 847 /* .pfnCreate = */ atsTcpCreate, 848 /* .pfnDestroy = */ atsTcpDestroy, 849 /* .pfnOption = */ atsTcpOption, 850 /* .pfnStart = */ atsTcpStart, 412 851 /* .pfnTerm = */ atsTcpTerm, 413 852 /* .pfnWaitForConnect = */ atsTcpWaitForConnect, -
trunk/src/VBox/Devices/Audio/DrvHostAudioValidationKit.cpp
r89890 r89962 1024 1024 1025 1025 /** @todo Make this configurable via CFGM. */ 1026 const char *pszTcpAddr = ATS_TCP_HOST_DEFAULT_ADDR_STR;1027 uint32_t uTcpPort = ATS_TCP_HOST_DEFAULT_PORT;1026 const char *pszTcpAddr = "127.0.0.1"; /* Only reachable for localhost for now. */ 1027 uint32_t uTcpPort = ATS_TCP_DEF_BIND_PORT_VALKIT; 1028 1028 1029 1029 LogRel(("ValKit: Starting Audio Test Service (ATS) at %s:%RU32...\n", 1030 1030 pszTcpAddr, uTcpPort)); 1031 1031 1032 rc = AudioTestSvcInit(&pThis->Srv, 1033 /* We only allow connections from localhost for now. */ 1034 pszTcpAddr, uTcpPort, &Callbacks); 1035 if (RT_SUCCESS(rc)) 1036 rc = AudioTestSvcStart(&pThis->Srv); 1032 rc = AudioTestSvcCreate(&pThis->Srv); 1033 if (RT_SUCCESS(rc)) 1034 { 1035 RTGETOPTUNION Val; 1036 RT_ZERO(Val); 1037 1038 Val.psz = "server"; /** @ŧodo No client connection mode needed here (yet). Make this configurable via CFGM. */ 1039 rc = AudioTestSvcHandleOption(&pThis->Srv, ATSTCPOPT_MODE, &Val); 1040 AssertRC(rc); 1041 1042 Val.psz = pszTcpAddr; 1043 rc = AudioTestSvcHandleOption(&pThis->Srv, ATSTCPOPT_BIND_ADDRESS, &Val); 1044 AssertRC(rc); 1045 1046 Val.u16 = uTcpPort; 1047 rc = AudioTestSvcHandleOption(&pThis->Srv, ATSTCPOPT_BIND_PORT, &Val); 1048 AssertRC(rc); 1049 1050 rc = AudioTestSvcInit(&pThis->Srv, &Callbacks); 1051 if (RT_SUCCESS(rc)) 1052 rc = AudioTestSvcStart(&pThis->Srv); 1053 } 1037 1054 1038 1055 if (RT_SUCCESS(rc)) -
trunk/src/VBox/Devices/Audio/testcase/tstAudioTestService.cpp
r89805 r89962 76 76 77 77 ATSSERVER Srv; 78 rc = AudioTestSvc Init(&Srv, "127.0.0.1", ATS_TCP_HOST_DEFAULT_PORT, &Callbacks);78 rc = AudioTestSvcCreate(&Srv); 79 79 RTTEST_CHECK_RC_OK(hTest, rc); 80 80 if (RT_SUCCESS(rc)) 81 81 { 82 rc = AudioTestSvc Start(&Srv);82 rc = AudioTestSvcInit(&Srv, &Callbacks); 83 83 RTTEST_CHECK_RC_OK(hTest, rc); 84 84 if (RT_SUCCESS(rc)) 85 85 { 86 rc = AudioTestSvc ClientConnect(&Client, "127.0.0.1", ATS_TCP_HOST_DEFAULT_PORT);86 rc = AudioTestSvcStart(&Srv); 87 87 RTTEST_CHECK_RC_OK(hTest, rc); 88 if (RT_SUCCESS(rc)) 89 { 90 RTGETOPTUNION Val; 91 RT_ZERO(Val); 92 93 Val.psz = ATS_TCP_DEF_CONNECT_HOST_ADDR_STR; 94 rc = AudioTestSvcClientHandleOption(&Client, ATSTCPOPT_CONNECT_ADDRESS, &Val); 95 AssertRC(rc); 96 97 Val.u16 = ATS_TCP_DEF_CONNECT_PORT_HOST_PORT_FWD; 98 rc = AudioTestSvcClientHandleOption(&Client, ATSTCPOPT_CONNECT_PORT, &Val); 99 AssertRC(rc); 100 101 rc = AudioTestSvcClientConnect(&Client); 102 RTTEST_CHECK_RC_OK(hTest, rc); 103 } 88 104 } 89 105 } -
trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp
r89891 r89962 635 635 RT_ZERO(TstEnv); 636 636 637 int rc = AudioTestSvcCreate(&TstEnv.u.Guest.Srv); 638 637 639 const char *pszDevice = NULL; /* Custom device to use. Can be NULL if not being used. */ 638 640 const char *pszTag = NULL; /* Custom tag to use. Can be NULL if not being used. */ … … 645 647 646 648 const char *pszGuestTcpAddr = NULL; 647 uint16_t uGuestTcpPort = ATS_TCP_ GUEST_DEFAULT_PORT;649 uint16_t uGuestTcpPort = ATS_TCP_DEF_BIND_PORT_GUEST; 648 650 const char *pszValKitTcpAddr = NULL; 649 uint16_t uValKitTcpPort = ATS_TCP_ HOST_DEFAULT_PORT;650 651 int rc;651 uint16_t uValKitTcpPort = ATS_TCP_DEF_BIND_PORT_VALKIT; 652 653 int ch; 652 654 RTGETOPTUNION ValueUnion; 653 while (( rc= RTGetOpt(pGetState, &ValueUnion)))654 { 655 switch ( rc)655 while ((ch = RTGetOpt(pGetState, &ValueUnion))) 656 { 657 switch (ch) 656 658 { 657 659 case 'a': … … 757 759 758 760 default: 759 return RTGetOptPrintError(rc, &ValueUnion); 761 rc = AudioTestSvcHandleOption(&TstEnv.u.Guest.Srv, ch, &ValueUnion); 762 if (RT_FAILURE(rc)) 763 return RTGetOptPrintError(rc, &ValueUnion); 760 764 } 761 765 } … … 774 778 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No test mode (--mode) specified!\n"); 775 779 776 if (TstEnv.enmMode == AUDIOTESTMODE_HOST)777 {778 if (!pszGuestTcpAddr)779 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No guest ATS address (--guest-ats-addr) specified!\n");780 }781 782 780 /* For now all tests have the same test environment. */ 783 rc = audioTestEnvInit(&TstEnv, pDrvReg, fWithDrvAudio, 784 pszValKitTcpAddr, uValKitTcpPort, 785 pszGuestTcpAddr, uGuestTcpPort); 781 rc = audioTestEnvInit(&TstEnv, pDrvReg, fWithDrvAudio); 786 782 if (RT_SUCCESS(rc)) 787 783 rc = audioTestWorker(&TstEnv); … … 806 802 g_aCmdTestOptions, 807 803 RT_ELEMENTS(g_aCmdTestOptions), 808 audioTestCmdTestHelp 804 audioTestCmdTestHelp, 805 true /* fNeedsTransport */ 809 806 }; 810 807 … … 985 982 RT_ELEMENTS(g_aCmdVerifyOptions), 986 983 NULL, 984 false /* fNeedsTransport */ 987 985 }; 988 986 … … 1067 1065 RTStrmPrintf(pStrm, " %s\n", pszHelp); 1068 1066 } 1067 1068 if (pCmd->fNeedsTransport) 1069 { 1070 for (uintptr_t iTx = 0; iTx < g_cTransports; iTx++) 1071 g_apTransports[iTx]->pfnUsage(pStrm); 1072 } 1069 1073 } 1070 1074 … … 1155 1159 if (strcmp(ValueUnion.psz, pCmd->pszCommand) == 0) 1156 1160 { 1157 size_t const cCombinedOptions = pCmd->cOptions + RT_ELEMENTS(g_aCmdCommonOptions); 1161 size_t cCombinedOptions = pCmd->cOptions + RT_ELEMENTS(g_aCmdCommonOptions); 1162 if (pCmd->fNeedsTransport) 1163 { 1164 for (uintptr_t iTx = 0; iTx < g_cTransports; iTx++) 1165 cCombinedOptions += g_apTransports[iTx]->cOpts; 1166 } 1158 1167 PRTGETOPTDEF paCombinedOptions = (PRTGETOPTDEF)RTMemAlloc(cCombinedOptions * sizeof(RTGETOPTDEF)); 1159 1168 if (paCombinedOptions) 1160 1169 { 1170 unsigned idxOpts = 0; 1161 1171 memcpy(paCombinedOptions, g_aCmdCommonOptions, sizeof(g_aCmdCommonOptions)); 1162 memcpy(&paCombinedOptions[RT_ELEMENTS(g_aCmdCommonOptions)], 1163 pCmd->paOptions, pCmd->cOptions * sizeof(RTGETOPTDEF)); 1172 idxOpts += RT_ELEMENTS(g_aCmdCommonOptions); 1173 memcpy(&paCombinedOptions[idxOpts], pCmd->paOptions, pCmd->cOptions * sizeof(RTGETOPTDEF)); 1174 idxOpts += pCmd->cOptions; 1175 if (pCmd->fNeedsTransport) 1176 { 1177 for (uintptr_t iTx = 0; iTx < g_cTransports; iTx++) 1178 { 1179 memcpy(&paCombinedOptions[idxOpts], 1180 g_apTransports[iTx]->paOpts, g_apTransports[iTx]->cOpts * sizeof(RTGETOPTDEF)); 1181 idxOpts += g_apTransports[iTx]->cOpts; 1182 } 1183 } 1164 1184 1165 1185 rc = RTGetOptInit(&GetState, argc, argv, paCombinedOptions, cCombinedOptions, -
trunk/src/VBox/ValidationKit/utils/audio/vkatCmdGeneric.cpp
r89643 r89962 157 157 RT_ELEMENTS(g_aCmdEnumOptions), 158 158 audioTestCmdEnumHelp, 159 false /* fNeedsTransport */ 159 160 }; 160 161 … … 486 487 RT_ELEMENTS(g_aCmdPlayOptions), 487 488 audioTestCmdPlayHelp, 489 false /* fNeedsTransport */ 488 490 }; 489 491 … … 866 868 RT_ELEMENTS(g_aCmdRecOptions), 867 869 audioTestCmdRecHelp, 870 false /* fNeedsTransport */ 868 871 }; 869 872 -
trunk/src/VBox/ValidationKit/utils/audio/vkatCmdSelfTest.cpp
r89890 r89962 77 77 2 /* 16-bit */, true /* fSigned */, 2 /* cChannels */, 44100 /* uHz */); 78 78 79 rc = audioTestEnvInit(pTstEnvGst, pTstEnvGst->DrvStack.pDrvReg, pCtx->fWithDrvAudio, 80 pCtx->Host.szValKitAtsAddr, pCtx->Host.uValKitAtsPort, 81 pCtx->Guest.szAtsAddr, pCtx->Guest.uAtsPort); 79 rc = audioTestEnvInit(pTstEnvGst, pTstEnvGst->DrvStack.pDrvReg, pCtx->fWithDrvAudio); 82 80 if (RT_SUCCESS(rc)) 83 81 { … … 159 157 pTstEnvHst->enmMode = AUDIOTESTMODE_HOST; 160 158 161 rc = audioTestEnvInit(pTstEnvHst, &g_DrvHostValidationKitAudio, true /* fWithDrvAudio */, 162 pCtx->Host.szValKitAtsAddr, pCtx->Host.uValKitAtsPort, 163 pCtx->Host.szGuestAtsAddr, pCtx->Host.uGuestAtsPort); 159 rc = audioTestEnvInit(pTstEnvHst, &g_DrvHostValidationKitAudio, true /* fWithDrvAudio */); 164 160 if (RT_SUCCESS(rc)) 165 161 { … … 346 342 RT_ELEMENTS(s_aCmdSelftestOptions), 347 343 audioTestCmdSelftestHelp, 344 true /* fNeedsTransport */ 348 345 }; 349 346 -
trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp
r89892 r89962 574 574 *********************************************************************************************************************************/ 575 575 576 int audioTestEnvConnectToHostAts(PAUDIOTESTENV pTstEnv, 577 const char *pszHostTcpAddr, uint32_t uHostTcpPort) 578 { 579 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connecting to host ATS at %s:%RU32 ...\n", 580 (pszHostTcpAddr && *pszHostTcpAddr) ? pszHostTcpAddr : ATS_TCP_HOST_DEFAULT_ADDR_STR, 581 uHostTcpPort ? uHostTcpPort : ATS_TCP_HOST_DEFAULT_PORT); 582 583 int rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.AtsClValKit, pszHostTcpAddr, uHostTcpPort); 576 /** 577 * Connects an ATS client via TCP/IP to a peer. 578 * 579 * @returns VBox status code. 580 * @param pTstEnv Test environment to use. 581 * @param pClient Client to connect. 582 * @param pszWhat Hint of what to connect to where. 583 * @param pszTcpBindAddr TCP/IP bind address. Optionl and can be NULL. 584 * Server mode will be disabled then. 585 * @param uTcpBindPort TCP/IP bind port. Optionl and can be 0. 586 * Server mode will be disabled then. * 587 * @param pszTcpConnectAddr TCP/IP connect address. Optionl and can be NULL. 588 * Client mode will be disabled then. 589 * @param uTcpConnectPort TCP/IP connect port. Optionl and can be 0. 590 * Client mode will be disabled then. 591 */ 592 int audioTestEnvConnectViaTcp(PAUDIOTESTENV pTstEnv, PATSCLIENT pClient, const char *pszWhat, 593 const char *pszTcpBindAddr, uint16_t uTcpBindPort, 594 const char *pszTcpConnectAddr, uint16_t uTcpConnectPort) 595 { 596 RT_NOREF(pTstEnv); 597 598 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connecting %s ...\n", pszWhat); 599 600 RTGETOPTUNION Val; 601 RT_ZERO(Val); 602 603 int rc; 604 605 if ( !pszTcpBindAddr 606 || !uTcpBindPort) 607 { 608 Val.psz = "client"; 609 } 610 else if ( !pszTcpConnectAddr 611 || !uTcpConnectPort) 612 { 613 Val.psz = "server"; 614 } 615 else 616 Val.psz = "both"; 617 618 rc = AudioTestSvcClientHandleOption(pClient, ATSTCPOPT_MODE, &Val); 619 AssertRCReturn(rc, rc); 620 621 if ( !RTStrCmp(Val.psz, "client") 622 || !RTStrCmp(Val.psz, "both")) 623 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connecting at %s:%RU32\n", pszTcpConnectAddr, uTcpConnectPort); 624 625 if ( !RTStrCmp(Val.psz, "server") 626 || !RTStrCmp(Val.psz, "both")) 627 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Listening at %s:%RU32\n", pszTcpBindAddr ? pszTcpBindAddr : "<None>", uTcpBindPort); 628 629 if (pszTcpBindAddr) 630 { 631 Val.psz = pszTcpBindAddr; 632 rc = AudioTestSvcClientHandleOption(pClient, ATSTCPOPT_BIND_ADDRESS, &Val); 633 AssertRCReturn(rc, rc); 634 } 635 636 if (uTcpBindPort) 637 { 638 Val.u16 = uTcpBindPort; 639 rc = AudioTestSvcClientHandleOption(pClient, ATSTCPOPT_BIND_PORT, &Val); 640 AssertRCReturn(rc, rc); 641 } 642 643 if (pszTcpConnectAddr) 644 { 645 Val.psz = pszTcpConnectAddr; 646 rc = AudioTestSvcClientHandleOption(pClient, ATSTCPOPT_CONNECT_ADDRESS, &Val); 647 AssertRCReturn(rc, rc); 648 } 649 650 if (uTcpConnectPort) 651 { 652 Val.u16 = uTcpConnectPort; 653 rc = AudioTestSvcClientHandleOption(pClient, ATSTCPOPT_CONNECT_PORT, &Val); 654 AssertRCReturn(rc, rc); 655 } 656 657 rc = AudioTestSvcClientConnect(pClient); 584 658 if (RT_FAILURE(rc)) 585 659 { 586 RTTestFailed(g_hTest, "Connecting to host ATS failed with %Rrc\n", rc);660 RTTestFailed(g_hTest, "Connecting %s failed with %Rrc\n", pszWhat, rc); 587 661 return rc; 588 662 } 589 663 590 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connected to host ATS\n"); 591 return rc; 592 } 593 594 int audioTestEnvConnectToGuestAts(PAUDIOTESTENV pTstEnv, 595 const char *pszGuestTcpAddr, uint32_t uGuestTcpPort) 596 { 597 RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Connecting to guest ATS at %s:%RU32 ...\n", 598 (pszGuestTcpAddr && *pszGuestTcpAddr) ? pszGuestTcpAddr : "127.0.0.1", 599 uGuestTcpPort ? uGuestTcpPort : ATS_TCP_GUEST_DEFAULT_PORT); 600 601 int rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.AtsClGuest, pszGuestTcpAddr, uGuestTcpPort); 664 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connected %s\n", pszWhat); 665 return rc; 666 } 667 668 /** 669 * Configures and starts an ATS TCP/IP server. 670 * 671 * @returns VBox status code. 672 * @param pSrv ATS server instance to configure and start. 673 * @param pCallbacks ATS callback table to use. 674 * @param pszDesc Hint of server type which is being started. 675 * @param pszTcpBindAddr TCP/IP bind address. Optionl and can be NULL. 676 * Server mode will be disabled then. 677 * @param uTcpBindPort TCP/IP bind port. Optionl and can be 0. 678 * Server mode will be disabled then. * 679 * @param pszTcpConnectAddr TCP/IP connect address. Optionl and can be NULL. 680 * Client mode will be disabled then. 681 * @param uTcpConnectPort TCP/IP connect port. Optionl and can be 0. 682 * Client mode will be disabled then. 683 */ 684 int audioTestEnvConfigureAndStartTcpServer(PATSSERVER pSrv, PCATSCALLBACKS pCallbacks, const char *pszDesc, 685 const char *pszTcpBindAddr, uint16_t uTcpBindPort, 686 const char *pszTcpConnectAddr, uint16_t uTcpConnectPort) 687 { 688 RTGETOPTUNION Val; 689 RT_ZERO(Val); 690 691 if (pszTcpBindAddr) 692 { 693 Val.psz = pszTcpBindAddr; 694 AudioTestSvcHandleOption(pSrv, ATSTCPOPT_BIND_ADDRESS, &Val); 695 } 696 697 if (uTcpBindPort) 698 { 699 Val.u16 = uTcpBindPort; 700 AudioTestSvcHandleOption(pSrv, ATSTCPOPT_BIND_PORT, &Val); 701 } 702 703 if (pszTcpConnectAddr) 704 { 705 Val.psz = pszTcpConnectAddr; 706 AudioTestSvcHandleOption(pSrv, ATSTCPOPT_CONNECT_ADDRESS, &Val); 707 } 708 709 if (uTcpConnectPort) 710 { 711 Val.u16 = uTcpConnectPort; 712 AudioTestSvcHandleOption(pSrv, ATSTCPOPT_CONNECT_PORT, &Val); 713 } 714 715 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Starting server for %s at %s:%RU32 ...\n", 716 pszDesc, pszTcpBindAddr[0] ? pszTcpBindAddr : "0.0.0.0", uTcpBindPort); 717 if (pszTcpConnectAddr[0]) 718 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Trying %s to connect as client to %s:%RU32 ...\n", 719 pszDesc, pszTcpConnectAddr[0] ? pszTcpConnectAddr : "0.0.0.0", uTcpConnectPort); 720 721 int rc = AudioTestSvcInit(pSrv, pCallbacks); 722 if (RT_SUCCESS(rc)) 723 rc = AudioTestSvcStart(pSrv); 724 602 725 if (RT_FAILURE(rc)) 603 { 604 RTTestFailed(g_hTest, "Connecting to guest ATS failed with %Rrc\n", rc); 605 return rc; 606 } 607 608 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connected to guest ATS\n"); 726 RTTestFailed(g_hTest, "Starting server for %s failed with %Rrc\n", pszDesc, rc); 727 609 728 return rc; 610 729 } … … 616 735 * @param pDrvReg Audio driver to use. 617 736 * @param fWithDrvAudio Whether to include DrvAudio in the stack or not. 618 * @param pszHostTcpAddr Host ATS TCP/IP address to connect to.619 * If NULL, ATS_TCP_HOST_DEFAULT_ADDR_STR will be used.620 * @param uHostTcpPort Host ATS TCP/IP port to connect to.621 * If 0, ATS_TCP_HOST_DEFAULT_PORT will be used.622 * @param pszGuestTcpAddr Guest ATS TCP/IP address to connect to.623 * If NULL, any address (0.0.0.0) will be used.624 * @param uGuestTcpPort Guest ATS TCP/IP port to connect to.625 * If 0, ATS_TCP_GUEST_DEFAULT_PORT will be used.626 737 */ 627 738 int audioTestEnvInit(PAUDIOTESTENV pTstEnv, 628 PCPDMDRVREG pDrvReg, bool fWithDrvAudio, 629 const char *pszHostTcpAddr, uint32_t uHostTcpPort, 630 const char *pszGuestTcpAddr, uint32_t uGuestTcpPort) 739 PCPDMDRVREG pDrvReg, bool fWithDrvAudio) 631 740 { 632 741 int rc = VINF_SUCCESS; … … 656 765 if (!pDrvReg) 657 766 pDrvReg = AudioTestGetDefaultBackend(); 658 659 if (!uHostTcpPort)660 uHostTcpPort = ATS_TCP_HOST_DEFAULT_PORT;661 662 if (!uGuestTcpPort)663 uGuestTcpPort = ATS_TCP_GUEST_DEFAULT_PORT;664 767 665 768 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Initializing environment for mode '%s'\n", pTstEnv->enmMode == AUDIOTESTMODE_HOST ? "host" : "guest"); … … 732 835 return rc; 733 836 734 /** @todo Implement NAT mode like we do for TxS later? */735 837 if (pTstEnv->enmMode == AUDIOTESTMODE_GUEST) 736 838 { … … 749 851 Callbacks.pvUser = &Ctx; 750 852 853 if (!pTstEnv->u.Guest.TcpOpts.uTcpBindPort) 854 pTstEnv->u.Guest.TcpOpts.uTcpBindPort = ATS_TCP_DEF_BIND_PORT_GUEST; 855 856 if (!pTstEnv->u.Guest.TcpOpts.szTcpBindAddr[0]) 857 RTStrCopy(pTstEnv->u.Guest.TcpOpts.szTcpBindAddr, sizeof(pTstEnv->u.Guest.TcpOpts.szTcpBindAddr), "0.0.0.0"); 858 859 if (!pTstEnv->u.Guest.TcpOpts.uTcpConnectPort) 860 pTstEnv->u.Guest.TcpOpts.uTcpConnectPort = ATS_TCP_DEF_CONNECT_PORT_GUEST; 861 862 if (!pTstEnv->u.Guest.TcpOpts.szTcpConnectAddr[0]) 863 RTStrCopy(pTstEnv->u.Guest.TcpOpts.szTcpConnectAddr, sizeof(pTstEnv->u.Guest.TcpOpts.szTcpConnectAddr), "10.0.2.2"); 864 751 865 /* 752 866 * Start the ATS (Audio Test Service) on the guest side. … … 756 870 * Note that we have to bind to "0.0.0.0" by default so that the host can connect to it. 757 871 */ 758 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Starting guest ATS at %s:%RU32...\n", 759 (pszGuestTcpAddr && *pszGuestTcpAddr) ? pszGuestTcpAddr : "0.0.0.0", uGuestTcpPort); 760 rc = AudioTestSvcInit(&pTstEnv->u.Guest.Srv, 761 (pszGuestTcpAddr && *pszGuestTcpAddr) ? pszGuestTcpAddr : "0.0.0.0", uGuestTcpPort, &Callbacks); 872 rc = audioTestEnvConfigureAndStartTcpServer(&pTstEnv->u.Guest.Srv, &Callbacks, "Guest ATS", 873 pTstEnv->u.Guest.TcpOpts.szTcpBindAddr, pTstEnv->u.Guest.TcpOpts.uTcpBindPort, 874 pTstEnv->u.Guest.TcpOpts.szTcpConnectAddr, pTstEnv->u.Guest.TcpOpts.uTcpConnectPort); 875 876 } 877 else /* Host mode */ 878 { 879 880 ATSCALLBACKCTX Ctx; 881 Ctx.pTstEnv = pTstEnv; 882 883 ATSCALLBACKS Callbacks; 884 RT_ZERO(Callbacks); 885 Callbacks.pvUser = &Ctx; 886 887 if (!pTstEnv->u.Host.TcpOpts.uTcpBindPort) 888 pTstEnv->u.Host.TcpOpts.uTcpBindPort = ATS_TCP_DEF_BIND_PORT_HOST; 889 890 if (!pTstEnv->u.Host.TcpOpts.szTcpBindAddr[0]) 891 RTStrCopy(pTstEnv->u.Host.TcpOpts.szTcpBindAddr, sizeof(pTstEnv->u.Host.TcpOpts.szTcpBindAddr), "0.0.0.0"); 892 893 if (!pTstEnv->u.Host.TcpOpts.uTcpConnectPort) 894 pTstEnv->u.Host.TcpOpts.uTcpConnectPort = ATS_TCP_DEF_CONNECT_PORT_HOST_PORT_FWD; 895 896 if (!pTstEnv->u.Host.TcpOpts.szTcpConnectAddr[0]) 897 RTStrCopy(pTstEnv->u.Host.TcpOpts.szTcpConnectAddr, sizeof(pTstEnv->u.Host.TcpOpts.szTcpConnectAddr), 898 ATS_TCP_DEF_CONNECT_HOST_ADDR_STR); /** @todo Get VM IP? Needs port forwarding. */ 899 900 /* We need to start a server on the host so that VMs configured with NAT networking 901 * can connect to it as well. */ 902 rc = AudioTestSvcClientCreate(&pTstEnv->u.Host.AtsClGuest); 762 903 if (RT_SUCCESS(rc)) 763 rc = AudioTestSvcStart(&pTstEnv->u.Guest.Srv); 764 765 if (RT_FAILURE(rc)) 766 RTTestFailed(g_hTest, "Starting ATS failed with %Rrc\n", rc); 767 } 768 else /* Host mode */ 769 { 770 rc = audioTestEnvConnectToHostAts(pTstEnv, pszHostTcpAddr, uHostTcpPort); 904 rc = audioTestEnvConnectViaTcp(pTstEnv, &pTstEnv->u.Host.AtsClGuest, 905 "Host -> Guest ATS", 906 pTstEnv->u.Host.TcpOpts.szTcpBindAddr, pTstEnv->u.Host.TcpOpts.uTcpBindPort, 907 pTstEnv->u.Host.TcpOpts.szTcpConnectAddr, pTstEnv->u.Host.TcpOpts.uTcpConnectPort); 771 908 if (RT_SUCCESS(rc)) 772 rc = audioTestEnvConnectToGuestAts(pTstEnv, pszGuestTcpAddr, uGuestTcpPort); 909 { 910 if (!pTstEnv->ValKitTcpOpts.uTcpConnectPort) 911 pTstEnv->ValKitTcpOpts.uTcpConnectPort = ATS_TCP_DEF_CONNECT_PORT_VALKIT; 912 913 if (!pTstEnv->ValKitTcpOpts.szTcpConnectAddr[0]) 914 RTStrCopy(pTstEnv->ValKitTcpOpts.szTcpConnectAddr, sizeof(pTstEnv->ValKitTcpOpts.szTcpConnectAddr), 915 ATS_TCP_DEF_CONNECT_HOST_ADDR_STR); 916 917 rc = AudioTestSvcClientCreate(&pTstEnv->u.Host.AtsClValKit); 918 if (RT_SUCCESS(rc)) 919 rc = audioTestEnvConnectViaTcp(pTstEnv, &pTstEnv->u.Host.AtsClValKit, 920 "Host -> Validation Kit Host Audio Driver ATS", 921 pTstEnv->ValKitTcpOpts.szTcpBindAddr, pTstEnv->ValKitTcpOpts.uTcpBindPort, 922 pTstEnv->ValKitTcpOpts.szTcpConnectAddr, pTstEnv->ValKitTcpOpts.uTcpConnectPort); 923 } 773 924 } 774 925 -
trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h
r89890 r89962 173 173 /** Maximum audio streams a test environment can handle. */ 174 174 #define AUDIOTESTENV_MAX_STREAMS 8 175 176 /** 177 * Structure for keeping TCP/IP-specific options. 178 */ 179 typedef struct AUDIOTESTENVTCPOPTS 180 { 181 /** Bind address (server mode). When empty, "0.0.0.0" (any host) will be used. */ 182 char szTcpBindAddr[128]; 183 /** Bind port (server mode). */ 184 uint16_t uTcpBindPort; 185 /** Connection address (client mode). */ 186 char szTcpConnectAddr[128]; 187 /** Connection port (client mode). */ 188 uint16_t uTcpConnectPort; 189 } AUDIOTESTENVTCPOPTS; 190 typedef AUDIOTESTENVTCPOPTS *PAUDIOTESTENVTCPOPTS; 175 191 176 192 /** … … 218 234 struct 219 235 { 236 AUDIOTESTENVTCPOPTS TcpOpts; 220 237 /** ATS instance to use. */ 221 ATSSERVER Srv;238 ATSSERVER Srv; 222 239 } Guest; 223 240 struct 224 241 { 242 AUDIOTESTENVTCPOPTS TcpOpts; 243 /** ATS instance to use. */ 244 ATSSERVER Srv; 225 245 /** Client connected to the ATS on the guest side. */ 226 246 ATSCLIENT AtsClGuest; … … 233 253 } Host; 234 254 } u; 255 AUDIOTESTENVTCPOPTS ValKitTcpOpts; 235 256 } AUDIOTESTENV; 236 257 … … 312 333 /** Gets help for an option. */ 313 334 DECLCALLBACKMEMBER(const char *, pfnOptionHelp,(PCRTGETOPTDEF pOpt)); 335 /** Flag indicating if the command needs the ATS transport layer. 336 * Needed for command line parsing. */ 337 bool fNeedsTransport; 314 338 } VKATCMD; 315 339 /** Pointer to a const VKAT command entry. */ … … 423 447 /** @name ATS routines 424 448 * @{ */ 425 int audioTestEnvConnectTo HostAts(PAUDIOTESTENV pTstEnv,449 int audioTestEnvConnectToValKitAts(PAUDIOTESTENV pTstEnv, 426 450 const char *pszHostTcpAddr, uint32_t uHostTcpPort); 427 451 /** @} */ … … 429 453 /** @name Test environment handling 430 454 * @{ */ 431 int audioTestEnvInit(PAUDIOTESTENV pTstEnv, PCPDMDRVREG pDrvReg, bool fWithDrvAudio , const char *pszHostTcpAddr, uint32_t uHostTcpPort, const char *pszGuestTcpAddr, uint32_t uGuestTcpPort);455 int audioTestEnvInit(PAUDIOTESTENV pTstEnv, PCPDMDRVREG pDrvReg, bool fWithDrvAudio); 432 456 void audioTestEnvDestroy(PAUDIOTESTENV pTstEnv); 433 457 int audioTestEnvPrologue(PAUDIOTESTENV pTstEnv, bool fPack, char *pszPackFile, size_t cbPackFile);
Note:
See TracChangeset
for help on using the changeset viewer.