Changeset 60287 in vbox for trunk/src/VBox/ValidationKit/utils/usb/UsbTestService.cpp
- Timestamp:
- Apr 1, 2016 12:49:19 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 106330
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/usb/UsbTestService.cpp
r60280 r60287 56 56 57 57 #include "UsbTestServiceInternal.h" 58 #include "UsbTestServiceCfg.h" 58 59 59 60 … … 64 65 65 66 /** 67 * UTS client state. 68 */ 69 typedef enum UTSCLIENTSTATE 70 { 71 /** Invalid client state. */ 72 UTSCLIENTSTATE_INVALID = 0, 73 /** Client is initialising, only the HOWDY and BYE packets are allowed. */ 74 UTSCLIENTSTATE_INITIALISING, 75 /** Client is in fully cuntional state and ready to process all requests. */ 76 UTSCLIENTSTATE_READY, 77 /** Client is destroying. */ 78 UTSCLIENTSTATE_DESTROYING, 79 /** 32bit hack. */ 80 UTSCLIENTSTATE_32BIT_HACK = 0x7fffffff 81 } UTSCLIENTSTATE; 82 83 /** 66 84 * UTS client instance. 67 85 */ … … 70 88 /** List node for new clients. */ 71 89 RTLISTNODE NdLst; 90 /** The current client state. */ 91 UTSCLIENTSTATE enmState; 72 92 /** Transport backend specific data. */ 73 93 PUTSTRANSPORTCLIENT pTransportClient; 94 /** Client hostname. */ 95 char *pszHostname; 74 96 } UTSCLIENT; 75 97 /** Pointer to a UTS client instance. */ … … 93 115 /** The select transport layer. */ 94 116 static PCUTSTRANSPORT g_pTransport; 117 /** The scratch path. */ 118 static char g_szCfgPath[RTPATH_MAX]; 95 119 /** The scratch path. */ 96 120 static char g_szScratchPath[RTPATH_MAX]; … … 118 142 * @todo implement signals and stuff. */ 119 143 static bool volatile g_fTerminate = false; 144 /** Configuration AST. */ 145 static PCFGAST g_pCfgAst = NULL; 120 146 /** Pipe for communicating with the serving thread about new clients. - read end */ 121 147 static RTPIPE g_hPipeR; … … 129 155 static RTLISTANCHOR g_LstClientsNew; 130 156 157 158 159 /** 160 * Returns the string represenation of the given state. 161 */ 162 static const char *utsClientStateStringify(UTSCLIENTSTATE enmState) 163 { 164 switch (enmState) 165 { 166 case UTSCLIENTSTATE_INVALID: 167 return "INVALID"; 168 case UTSCLIENTSTATE_INITIALISING: 169 return "INITIALISING"; 170 case UTSCLIENTSTATE_READY: 171 return "READY"; 172 case UTSCLIENTSTATE_DESTROYING: 173 return "DESTROYING"; 174 case UTSCLIENTSTATE_32BIT_HACK: 175 default: 176 break; 177 } 178 179 AssertMsgFailed(("Unknown state %#x\n", enmState)); 180 return "UNKNOWN"; 181 } 131 182 132 183 /** … … 451 502 452 503 /** 453 * Checks if the two opcodes match. 454 * 455 * @returns true on match, false on mismatch. 456 * @param pPktHdr The packet header. 457 * @param pszOpcode2 The opcode we're comparing with. Does not have 458 * to be the whole 8 chars long. 459 */ 460 DECLINLINE(bool) utsIsSameOpcode(PCUTSPKTHDR pPktHdr, const char *pszOpcode2) 461 { 462 if (pPktHdr->achOpcode[0] != pszOpcode2[0]) 463 return false; 464 if (pPktHdr->achOpcode[1] != pszOpcode2[1]) 465 return false; 466 467 unsigned i = 2; 468 while ( i < RT_SIZEOFMEMB(UTSPKTHDR, achOpcode) 469 && pszOpcode2[i] != '\0') 470 { 471 if (pPktHdr->achOpcode[i] != pszOpcode2[i]) 472 break; 473 i++; 474 } 475 476 if ( i < RT_SIZEOFMEMB(UTSPKTHDR, achOpcode) 477 && pszOpcode2[i] == '\0') 478 { 479 while ( i < RT_SIZEOFMEMB(UTSPKTHDR, achOpcode) 480 && pPktHdr->achOpcode[i] == ' ') 481 i++; 482 } 483 484 return i == RT_SIZEOFMEMB(UTSPKTHDR, achOpcode); 504 * Deals with a command which contains an unterminated string. 505 * 506 * @returns IPRT status code of the send. 507 * @param pClient The UTS client structure. 508 * @param pPktHdr The packet containing the unterminated string. 509 */ 510 static int utsReplyBadStrTermination(PUTSCLIENT pClient, PCUTSPKTHDR pPktHdr) 511 { 512 return utsReplyFailure(pClient, pPktHdr, "BAD TERM", VERR_INVALID_PARAMETER, "Opcode '%.8s' contains an unterminated string", pPktHdr->achOpcode); 513 } 514 515 /** 516 * Deals with a command sent in an invalid client state. 517 * 518 * @returns IPRT status code of the send. 519 * @param pClient The UTS client structure. 520 * @param pPktHdr The packet containing the unterminated string. 521 */ 522 static int utsReplyInvalidState(PUTSCLIENT pClient, PCUTSPKTHDR pPktHdr) 523 { 524 return utsReplyFailure(pClient, pPktHdr, "INVSTATE", VERR_INVALID_STATE, "Opcode '%.8s' is not supported at client state '%s", 525 pPktHdr->achOpcode, utsClientStateStringify(pClient->enmState)); 485 526 } 486 527 … … 512 553 static int utsDoHowdy(PUTSCLIENT pClient, PCUTSPKTHDR pPktHdr) 513 554 { 514 if (pPktHdr->cb != sizeof(UTSPKTHDR)) 515 return utsReplyBadSize(pClient, pPktHdr, sizeof(UTSPKTHDR)); 555 if (pPktHdr->cb != sizeof(UTSPKTREQHOWDY)) 556 return utsReplyBadSize(pClient, pPktHdr, sizeof(UTSPKTREQHOWDY)); 557 558 if (pClient->enmState != UTSCLIENTSTATE_INITIALISING) 559 return utsReplyInvalidState(pClient, pPktHdr); 560 561 PUTSPKTREQHOWDY pReq = (PUTSPKTREQHOWDY)pPktHdr; 562 563 if (pReq->uVersion != UTS_PROTOCOL_VS) 564 return utsReplyRC(pClient, pPktHdr, VERR_VERSION_MISMATCH, "The given version %#x is not supported", pReq->uVersion); 565 566 /* Verify hostname string. */ 567 if (pReq->cchHostname >= sizeof(pReq->achHostname)) 568 return utsReplyBadSize(pClient, pPktHdr, sizeof(pReq->achHostname) - 1); 569 570 if (pReq->achHostname[pReq->cchHostname] != '\0') 571 return utsReplyBadStrTermination(pClient, pPktHdr); 572 573 /* Extract string. */ 574 pClient->pszHostname = RTStrDup(pClient->pszHostname); 575 if (!pClient->pszHostname) 576 return utsReplyRC(pClient, pPktHdr, VERR_NO_MEMORY, "Failed to alllocate memory for the hostname string"); 577 516 578 int rc = utsReplyAck(pClient, pPktHdr); 517 579 if (RT_SUCCESS(rc)) … … 564 626 static void utsClientDestroy(PUTSCLIENT pClient) 565 627 { 628 if (pClient->pszHostname) 629 RTStrFree(pClient->pszHostname); 566 630 RTMemFree(pClient); 567 631 } … … 702 766 if (RT_LIKELY(pClient)) 703 767 { 768 pClient->enmState = UTSCLIENTSTATE_INITIALISING; 704 769 pClient->pTransportClient = pTransportClient; 705 770 } … … 724 789 { 725 790 int rc = VINF_SUCCESS; 791 PRTERRINFO pErrInfo = NULL; 726 792 727 793 RTListInit(&g_LstClientsNew); 728 794 729 rc = RTCritSectInit(&g_CritSectClients);795 rc = utsParseConfig(g_szCfgPath, &g_pCfgAst, &pErrInfo); 730 796 if (RT_SUCCESS(rc)) 731 797 { 732 rc = RT PipeCreate(&g_hPipeR, &g_hPipeW, 0);798 rc = RTCritSectInit(&g_CritSectClients); 733 799 if (RT_SUCCESS(rc)) 734 800 { 735 /* Spin off the thread serving connections. */ 736 rc = RTThreadCreate(&g_hThreadServing, utsClientWorker, NULL, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, 737 "USBTSTSRV"); 801 rc = RTPipeCreate(&g_hPipeR, &g_hPipeW, 0); 738 802 if (RT_SUCCESS(rc)) 739 return VINF_SUCCESS; 803 { 804 /* Spin off the thread serving connections. */ 805 rc = RTThreadCreate(&g_hThreadServing, utsClientWorker, NULL, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, 806 "USBTSTSRV"); 807 if (RT_SUCCESS(rc)) 808 return VINF_SUCCESS; 809 else 810 RTMsgError("Creating the client worker thread failed with %Rrc\n", rc); 811 812 RTPipeClose(g_hPipeR); 813 RTPipeClose(g_hPipeW); 814 } 740 815 else 741 RTMsgError("Creating the client worker thread failed with %Rrc\n", rc); 742 743 RTPipeClose(g_hPipeR); 744 RTPipeClose(g_hPipeW); 816 RTMsgError("Creating communications pipe failed with %Rrc\n", rc); 817 818 RTCritSectDelete(&g_CritSectClients); 745 819 } 746 820 else 747 RTMsgError("Creating communications pipefailed with %Rrc\n", rc);748 749 RTCritSectDelete(&g_CritSectClients);821 RTMsgError("Creating global critical section failed with %Rrc\n", rc); 822 823 utsConfigAstDestroy(g_pCfgAst); 750 824 } 751 825 else 752 RTMsgError("Creating global critical section failed with %Rrc\n", rc); 826 { 827 if (RTErrInfoIsSet(pErrInfo)) 828 { 829 RTMsgError("Failed to parse config with detailed error: %s (%Rrc)\n", 830 pErrInfo->pszMsg, pErrInfo->rc); 831 RTErrInfoFree(pErrInfo); 832 } 833 else 834 RTMsgError("Faield to parse config with unknown error (%Rrc)\n", rc); 835 return rc; 836 } 753 837 754 838 return rc; … … 821 905 822 906 /* 907 * Config file location. 908 */ 909 /** @todo: Improve */ 910 #if !defined(RT_OS_WINDOWS) 911 strcpy(g_szCfgPath, "/etc/uts.conf"); 912 #else 913 strcpy(g_szCfgPath, ""); 914 #endif 915 916 /* 823 917 * The default transporter is the first one. 824 918 */ … … 838 932 "\n" 839 933 "Options:\n" 934 " --config <path>\n" 935 " Where to load the config from\n" 840 936 " --cdrom <path>\n" 841 937 " Where the CD/DVD-ROM will be mounted.\n" … … 891 987 * Storage for locally handled options. 892 988 */ 893 bool fDaemonize= true;894 bool fDaemonized= false;989 bool fDaemonize = true; 990 bool fDaemonized = false; 895 991 896 992 /* … … 899 995 static const RTGETOPTDEF s_aBaseOptions[] = 900 996 { 997 { "--config", 'C', RTGETOPT_REQ_STRING }, 901 998 { "--transport", 't', RTGETOPT_REQ_STRING }, 902 999 { "--cdrom", 'c', RTGETOPT_REQ_STRING }, … … 937 1034 switch (ch) 938 1035 { 1036 case 'C': 1037 rc = RTStrCopy(g_szCfgPath, sizeof(g_szCfgPath), Val.psz); 1038 if (RT_FAILURE(rc)) 1039 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Config file path is path too long (%Rrc)\n", rc); 1040 break; 1041 939 1042 case 'c': 940 1043 rc = RTStrCopy(g_szCdRomPath, sizeof(g_szCdRomPath), Val.psz);
Note:
See TracChangeset
for help on using the changeset viewer.