VirtualBox

Changeset 60429 in vbox


Ignore:
Timestamp:
Apr 11, 2016 3:42:41 PM (8 years ago)
Author:
vboxsync
Message:

ValidationKit/usb/UsbTestService: Start on the client side, use txsclient.py as a template

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/tests/usb/usbgadget2.py

    r60375 r60429  
    44
    55"""
    6 Test eXecution Service Client.
     6UTS (USB Test Service) client.
    77"""
    88__copyright__ = \
    99"""
    10 Copyright (C) 2010-2015 Oracle Corporation
     10Copyright (C) 2010-2016 Oracle Corporation
    1111
    1212This file is part of VirtualBox Open Source Edition (OSE), as
     
    4747from testdriver.base    import TdTaskBase;
    4848
     49## @name USB gadget impersonation string constants.
     50## @{
     51g_ksGadgetImpersonationInvalid = 'Invalid';
     52g_ksGadgetImpersonationTest    = 'Test';
     53g_ksGadgetImpersonationMsd     = 'Msd';
     54g_ksGadgetImpersonationWebcam  = 'Webcam';
     55g_ksGadgetImpersonationEther   = 'Ether';
     56## @}
     57
     58## @name USB gadget type used in the UTS protocol.
     59## @{
     60g_kiGadgetTypeTest             = 1;
     61## @}
     62
     63## @name USB gadget access methods used in the UTS protocol.
     64## @{
     65g_kiGadgetAccessUsbIp          = 1;
     66## @}
     67
    4968#
    50 # Helpers for decoding data received from the TXS.
     69# Helpers for decoding data received from the UTS.
    5170# These are used both the Session and Transport classes.
    5271#
     
    112131
    113132#
    114 # Helper for encoding data sent to the TXS.
     133# Helper for encoding data sent to the UTS.
    115134#
    116135
     
    123142                         (u32 / 16777216) % 256) );
    124143
    125 
     144def u16ToByteArray(u16):
     145    """Encodes the u16 value as a little endian byte (B) array."""
     146    return array.array('B', \
     147                       (  u16        % 256, \
     148                         (u16 / 256) % 256) );
     149
     150def u8ToByteArray(u8):
     151    """Encodes the u8 value as a little endian byte (B) array."""
     152    return array.array('B', (u8 % 256);
    126153
    127154class TransportBase(object):
     
    153180    def connect(self, cMsTimeout):
    154181        """
    155         Quietly attempts to connect to the TXS.
     182        Quietly attempts to connect to the UTS.
    156183
    157184        Returns True on success.
     
    166193    def disconnect(self, fQuiet = False):
    167194        """
    168         Disconnect from the TXS.
     195        Disconnect from the UTS.
    169196
    170197        Returns True.
     
    177204    def sendBytes(self, abBuf, cMsTimeout):
    178205        """
    179         Sends the bytes in the buffer abBuf to the TXS.
     206        Sends the bytes in the buffer abBuf to the UTS.
    180207
    181208        Returns True on success.
     
    191218    def recvBytes(self, cb, cMsTimeout, fNoDataOk):
    192219        """
    193         Receive cb number of bytes from the TXS.
     220        Receive cb number of bytes from the UTS.
    194221
    195222        Returns the bytes (array('B')) on success.
     
    275302    def recvMsg(self, cMsTimeout, fNoDataOk = False):
    276303        """
    277         Receives a message from the TXS.
     304        Receives a message from the UTS.
    278305
    279306        Returns the message three-tuple: length, opcode, payload.
     
    376403class Session(TdTaskBase):
    377404    """
    378     A Test eXecution Service (TXS) client session.
     405    A USB Test Service (UTS) client session.
    379406    """
    380407
    381408    def __init__(self, oTransport, cMsTimeout, cMsIdleFudge, fTryConnect = False):
    382409        """
    383         Construct a TXS session.
    384 
    385         This starts by connecting to the TXS and will enter the signalled state
     410        Construct a UTS session.
     411
     412        This starts by connecting to the UTS and will enter the signalled state
    386413        when connected or the timeout has been reached.
    387414        """
     
    431458        """
    432459        if not self.cancelTask():
    433             reporter.maybeErr(not fIgnoreErrors, 'txsclient.Session.startTask: failed to cancel previous task.');
     460            reporter.maybeErr(not fIgnoreErrors, 'utsclient.Session.startTask: failed to cancel previous task.');
    434461            return False;
    435462
     
    438465        if self.sStatus != "":
    439466            self.unlockTask();
    440             reporter.maybeErr(not fIgnoreErrors, 'txsclient.Session.startTask: race.');
     467            reporter.maybeErr(not fIgnoreErrors, 'utsclient.Session.startTask: race.');
    441468            return False;
    442469        self.sStatus        = "setup";
     
    450477        self.fnTask         = fnTask;
    451478        self.aTaskArgs      = aArgs;
    452         self.oThread        = threading.Thread(target=self.taskThread, args=(), name=('TXS-%s' % (sStatus)));
     479        self.oThread        = threading.Thread(target=self.taskThread, args=(), name=('UTS-%s' % (sStatus)));
    453480        self.oThread.setDaemon(True);
    454481        self.msStart        = base.timestampMilli();
     
    478505            return False;
    479506
    480         reporter.log('txsclient: cancelling "%s"...' % (self.sStatus));
     507        reporter.log('utsclient: cancelling "%s"...' % (self.sStatus));
    481508        if self.sStatus == 'connecting':
    482509            self.oTransport.cancelConnect();
     
    561588    def recvAck(self, fNoDataOk = False):
    562589        """
    563         Receives an ACK or error response from the TXS.
     590        Receives an ACK or error response from the UTS.
    564591
    565592        Returns True on success.
     
    580607        Wrapper for recvAck and logging.
    581608        Returns True on success (ACK).
    582         Returns False on time, transport error and errors signalled by TXS.
     609        Returns False on time, transport error and errors signalled by UTS.
    583610        """
    584611        rc = self.recvAck(fNoDataOk);
     
    593620    def recvTrueFalse(self, sCommand):
    594621        """
    595         Receives a TRUE/FALSE response from the TXS.
     622        Receives a TRUE/FALSE response from the UTS.
    596623        Returns True on TRUE, False on FALSE and None on error/other (logged).
    597624        """
     
    644671
    645672    def taskConnect(self, cMsIdleFudge):
    646         """Tries to connect to the TXS"""
     673        """Tries to connect to the UTS"""
    647674        while not self.isCancelled():
    648675            reporter.log2('taskConnect: connecting ...');
     
    665692
    666693    def taskGreet(self, cMsIdleFudge):
    667         """Greets the TXS"""
     694        """Greets the UTS"""
    668695        rc = self.sendMsg("HOWDY", ());
    669696        if rc is True:
     
    678705
    679706    def taskBye(self):
    680         """Says goodbye to the TXS"""
     707        """Says goodbye to the UTS"""
    681708        rc = self.sendMsg("BYE");
    682709        if rc is True:
     
    685712        return rc;
    686713
    687     def taskUuid(self):
    688         """Gets the TXS UUID"""
    689         rc = self.sendMsg("UUID");
    690         if rc is True:
    691             rc = False;
    692             cbMsg, sOpcode, abPayload = self.recvReply();
    693             if cbMsg is not None:
    694                 sOpcode = sOpcode.strip()
    695                 if sOpcode == "ACK UUID":
    696                     sUuid = getSZ(abPayload, 0);
    697                     if sUuid is not None:
    698                         sUuid = '{%s}' % (sUuid,)
    699                         try:
    700                             _ = uuid.UUID(sUuid);
    701                             rc = sUuid;
    702                         except:
    703                             reporter.errorXcpt('taskUuid got an invalid UUID string %s' % (sUuid,));
    704                     else:
    705                         reporter.maybeErr(self.fErr, 'taskUuid did not get a UUID string.');
    706                 else:
    707                     reporter.maybeErr(self.fErr, 'taskUuid got a bad reply: %s' % (sOpcode,));
    708             else:
    709                 reporter.maybeErr(self.fErr, 'taskUuid got 3xNone from recvReply.');
     714    #
     715    # Gadget tasks.
     716    #
     717
     718    def taskGadgetCreate(self, iGadgetType, iGadgetAccess):
     719        """Creates a new gadget on UTS"""
     720        fRc = self.senfMsg("GDGTCRT", (iGadgetType, iGadgetAccess, 0));
     721        if fRc is True:
     722            fRc = self.recvAckLogged("GDGTCRT");
    710723        return rc;
    711724
    712     #
    713     # Process task
    714     # pylint: disable=C0111
    715     #
    716 
    717     def taskExecEx(self, sExecName, fFlags, asArgs, asAddEnv, oStdIn, oStdOut, oStdErr, oTestPipe, sAsUser): # pylint: disable=R0913,R0914,R0915,C0301
    718         # Construct the payload.
    719         aoPayload = [long(fFlags), '%s' % (sExecName), long(len(asArgs))];
    720         for sArg in asArgs:
    721             aoPayload.append('%s' % (sArg));
    722         aoPayload.append(long(len(asAddEnv)));
    723         for sPutEnv in asAddEnv:
    724             aoPayload.append('%s' % (sPutEnv));
    725         for o in (oStdIn, oStdOut, oStdErr, oTestPipe):
    726             if isinstance(o, basestring):
    727                 aoPayload.append(o);
    728             elif o is not None:
    729                 aoPayload.append('|');
    730                 o.uTxsClientCrc32 = zlib.crc32('');
    731             else:
    732                 aoPayload.append('');
    733         aoPayload.append('%s' % (sAsUser));
    734         aoPayload.append(long(self.cMsTimeout));
    735 
    736         # Kick of the EXEC command.
    737         rc = self.sendMsg('EXEC', aoPayload)
    738         if rc is True:
    739             rc = self.recvAckLogged('EXEC');
    740         if rc is True:
    741             # Loop till the process completes, feed input to the TXS and
    742             # receive output from it.
    743             sFailure                  = "";
    744             msPendingInputReply       = None;
    745             cbMsg, sOpcode, abPayload = (None, None, None);
    746             while True:
    747                 # Pending input?
    748                 if     msPendingInputReply is None \
    749                    and oStdIn is not None \
    750                    and not isinstance(oStdIn, basestring):
    751                     try:
    752                         abInput = oStdIn.read(65536);
    753                     except:
    754                         reporter.errorXcpt('read standard in');
    755                         sFailure = 'exception reading stdin';
    756                         rc = None;
    757                         break;
    758                     if len(abInput) > 0:
    759                         oStdIn.uTxsClientCrc32 = zlib.crc32(abInput, oStdIn.uTxsClientCrc32);
    760                         rc = self.sendMsg('STDIN', (long(oStdIn.uTxsClientCrc32 & 0xffffffff), abInput));
    761                         if rc is not True:
    762                             sFailure = 'sendMsg failure';
    763                             break;
    764                         msPendingInputReply = base.timestampMilli();
    765                         continue;
    766 
    767                 # Wait for input (500 ms timeout).
    768                 if cbMsg is None:
    769                     cbMsg, sOpcode, abPayload = self.recvReply(cMsTimeout=500, fNoDataOk=True);
    770                     if cbMsg == None:
    771                         # Check for time out before restarting the loop.
    772                         # Note! Only doing timeout checking here does mean that
    773                         #       the TXS may prevent us from timing out by
    774                         #       flooding us with data.  This is unlikely though.
    775                         if    self.hasTimedOut() \
    776                          and (   msPendingInputReply is None \
    777                               or base.timestampMilli() - msPendingInputReply > 30000):
    778                             reporter.maybeErr(self.fErr, 'taskExecEx: timed out');
    779                             sFailure = 'timeout';
    780                             rc = None;
    781                             break;
    782                         # Check that the connection is OK.
    783                         if not self.oTransport.isConnectionOk():
    784                             self.oTransport.disconnect();
    785                             sFailure = 'disconnected';
    786                             rc = False;
    787                             break;
    788                         continue;
    789 
    790                 # Handle the response.
    791                 sOpcode = sOpcode.rstrip();
    792                 if sOpcode == 'STDOUT':
    793                     oOut = oStdOut;
    794                 elif sOpcode == 'STDERR':
    795                     oOut = oStdErr;
    796                 elif sOpcode == 'TESTPIPE':
    797                     oOut = oTestPipe;
    798                 else:
    799                     oOut = None;
    800                 if oOut is not None:
    801                     # Output from the process.
    802                     if len(abPayload) < 4:
    803                         sFailure = 'malformed output packet (%s, %u bytes)' % (sOpcode, cbMsg);
    804                         reporter.maybeErr(self.fErr, 'taskExecEx: %s' % (sFailure));
    805                         rc = None;
    806                         break;
    807                     uStreamCrc32 = getU32(abPayload, 0);
    808                     oOut.uTxsClientCrc32 = zlib.crc32(abPayload[4:], oOut.uTxsClientCrc32);
    809                     if uStreamCrc32 != (oOut.uTxsClientCrc32 & 0xffffffff):
    810                         sFailure = 'crc error - mine=%#x their=%#x (%s, %u bytes)' \
    811                             % (oOut.uTxsClientCrc32 & 0xffffffff, uStreamCrc32, sOpcode, cbMsg);
    812                         reporter.maybeErr(self.fErr, 'taskExecEx: %s' % (sFailure));
    813                         rc = None;
    814                         break;
    815                     try:
    816                         oOut.write(abPayload[4:]);
    817                     except:
    818                         sFailure = 'exception writing %s' % (sOpcode);
    819                         reporter.errorXcpt('taskExecEx: %s' % (sFailure));
    820                         rc = None;
    821                         break;
    822                 elif sOpcode == 'STDINIGN' and msPendingInputReply is not None:
    823                     # Standard input is ignored.  Ignore this condition for now.
    824                     msPendingInputReply = None;
    825                     reporter.log('taskExecEx: Standard input is ignored... why?');
    826                     del oStdIn.uTxsClientCrc32;
    827                     oStdIn = '/dev/null';
    828                 elif  (sOpcode == 'STDINMEM' or sOpcode == 'STDINBAD' or sOpcode == 'STDINCRC')\
    829                   and msPendingInputReply is not None:
    830                     # TXS STDIN error, abort.
    831                     # TODO: STDINMEM - consider undoing the previous stdin read and try resubmitt it.
    832                     msPendingInputReply = None;
    833                     sFailure = 'TXS is out of memory for std input buffering';
    834                     reporter.maybeErr(self.fErr, 'taskExecEx: %s' % (sFailure));
    835                     rc = None;
    836                     break;
    837                 elif sOpcode == 'ACK' and msPendingInputReply is not None:
    838                     msPendingInputReply = None;
    839                 elif sOpcode.startswith('PROC '):
    840                     # Process status message, handle it outside the loop.
    841                     rc = True;
    842                     break;
    843                 else:
    844                     sFailure = 'Unexpected opcode %s' % (sOpcode);
    845                     reporter.maybeErr(self.fErr, 'taskExecEx: %s' % (sFailure));
    846                     rc = None;
    847                     break;
    848                 # Clear the message.
    849                 cbMsg, sOpcode, abPayload = (None, None, None);
    850 
    851             # If we sent an STDIN packet and didn't get a reply yet, we'll give
    852             # TXS some 5 seconds to reply to this.  If we don't wait here we'll
    853             # get screwed later on if we mix it up with the reply to some other
    854             # command.  Hackish.
    855             if msPendingInputReply is not None:
    856                 cbMsg2, sOpcode2, abPayload2 = self.oTransport.recvMsg(5000);
    857                 if cbMsg2 is not None:
    858                     reporter.log('taskExecEx: Out of order STDIN, got reply: %s, %s, %s [ignored]'
    859                                  % (cbMsg2, sOpcode2, abPayload2));
    860                     msPendingInputReply = None;
    861                 else:
    862                     reporter.maybeErr(self.fErr, 'taskExecEx: Pending STDIN, no reply after 5 secs!');
    863                     self.fScrewedUpMsgState = True;
    864 
    865             # Parse the exit status (True), abort (None) or do nothing (False).
    866             if rc is True:
    867                 if sOpcode == 'PROC OK':
    868                     rc = True;
    869                 else:
    870                     # Do proper parsing some other day if needed:
    871                     #   PROC TOK, PROC TOA, PROC DWN, PROC DOO,
    872                     #   PROC NOK + rc, PROC SIG + sig, PROC ABD, FAILED.
    873                     rc = False;
    874             else:
    875                 if rc is None:
    876                     # Abort it.
    877                     reporter.log('taskExecEx: sending ABORT...');
    878                     rc = self.sendMsg('ABORT');
    879                     while rc is True:
    880                         cbMsg, sOpcode, abPayload = self.oTransport.recvMsg(30000);
    881                         if cbMsg is None:
    882                             reporter.maybeErr(self.fErr, 'taskExecEx: Pending ABORT, no reply after 30 secs!')
    883                             self.fScrewedUpMsgState = True;
    884                             break;
    885                         if sOpcode.startswith('PROC '):
    886                             reporter.log('taskExecEx: ABORT reply: %s, %s, %s [ignored]' % (cbMsg, sOpcode, abPayload));
    887                             break;
    888                         reporter.log('taskExecEx: ABORT in process, ignoring reply: %s, %s, %s' % (cbMsg, sOpcode, abPayload));
    889                         # Check that the connection is OK before looping.
    890                         if not self.oTransport.isConnectionOk():
    891                             self.oTransport.disconnect();
    892                             break;
    893 
    894                 # Fake response with the reason why we quit.
    895                 if sFailure is not None:
    896                     self.t3oReply = (0, 'EXECFAIL', sFailure);
    897                 rc = None;
    898         else:
    899             rc = None;
    900 
    901         # Cleanup.
    902         for o in (oStdIn, oStdOut, oStdErr, oTestPipe):
    903             if o is not None and not isinstance(o, basestring):
    904                 del o.uTxsClientCrc32;      # pylint: disable=E1103
    905         reporter.log('taskExecEx: returns %s' % (rc));
     725    def taskGadgetDestroy(self, iGadgetId):
     726        """Destroys the given gadget handle on UTS"""
     727        fRc = self.senfMsg("GDGTDTOR", (iGadgetId, ));
     728        if fRc is True:
     729            fRc = self.recvAckLogged("GDGTDTOR");
    906730        return rc;
    907731
    908     #
    909     # Admin tasks
    910     #
    911 
    912     def hlpRebootShutdownWaitForAck(self, sCmd):
    913         """Wait for reboot/shutodwn ACK."""
    914         rc = self.recvAckLogged(sCmd);
    915         if rc is True:
    916             # poll a little while for server to disconnect.
    917             uMsStart = base.timestampMilli();
    918             while self.oTransport.isConnectionOk() \
    919               and base.timestampMilli() - uMsStart >= 5000:
    920                 if self.oTransport.isRecvPending(min(500, self.getMsLeft())):
    921                     break;
    922             self.oTransport.disconnect();
     732    def taskGadgetConnect(self, iGadgetId):
     733        """Connects the given gadget handle on UTS"""
     734        fRc = self.senfMsg("GDGTCNCT", (iGadgetId, ));
     735        if fRc is True:
     736            fRc = self.recvAckLogged("GDGTCNCT");
    923737        return rc;
    924738
    925     def taskReboot(self):
    926         rc = self.sendMsg('REBOOT');
    927         if rc is True:
    928             rc = self.hlpRebootShutdownWaitForAck('REBOOT');
     739    def taskGadgetDisconnect(self, iGadgetId):
     740        """Disconnects the given gadget handle from UTS"""
     741        fRc = self.senfMsg("GDGTDCNT", (iGadgetId, ));
     742        if fRc is True:
     743            fRc = self.recvAckLogged("GDGTDCNT");
    929744        return rc;
    930 
    931     def taskShutdown(self):
    932         rc = self.sendMsg('SHUTDOWN');
    933         if rc is True:
    934             rc = self.hlpRebootShutdownWaitForAck('SHUTDOWN');
    935         return rc;
    936 
    937     #
    938     # CD/DVD control tasks.
    939     #
    940 
    941     ## TODO
    942 
    943     #
    944     # File system tasks
    945     #
    946 
    947     def taskMkDir(self, sRemoteDir, fMode):
    948         rc = self.sendMsg('MKDIR', (fMode, sRemoteDir));
    949         if rc is True:
    950             rc = self.recvAckLogged('MKDIR');
    951         return rc;
    952 
    953     def taskMkDirPath(self, sRemoteDir, fMode):
    954         rc = self.sendMsg('MKDRPATH', (fMode, sRemoteDir));
    955         if rc is True:
    956             rc = self.recvAckLogged('MKDRPATH');
    957         return rc;
    958 
    959     def taskMkSymlink(self, sLinkTarget, sLink):
    960         rc = self.sendMsg('MKSYMLNK', (sLinkTarget, sLink));
    961         if rc is True:
    962             rc = self.recvAckLogged('MKSYMLNK');
    963         return rc;
    964 
    965     def taskRmDir(self, sRemoteDir):
    966         rc = self.sendMsg('RMDIR', (sRemoteDir,));
    967         if rc is True:
    968             rc = self.recvAckLogged('RMDIR');
    969         return rc;
    970 
    971     def taskRmFile(self, sRemoteFile):
    972         rc = self.sendMsg('RMFILE', (sRemoteFile,));
    973         if rc is True:
    974             rc = self.recvAckLogged('RMFILE');
    975         return rc;
    976 
    977     def taskRmSymlink(self, sRemoteSymlink):
    978         rc = self.sendMsg('RMSYMLNK', (sRemoteSymlink,));
    979         if rc is True:
    980             rc = self.recvAckLogged('RMSYMLNK');
    981         return rc;
    982 
    983     def taskRmTree(self, sRemoteTree):
    984         rc = self.sendMsg('RMTREE', (sRemoteTree,));
    985         if rc is True:
    986             rc = self.recvAckLogged('RMTREE');
    987         return rc;
    988 
    989     #def "CHMOD   "
    990     #def "CHOWN   "
    991     #def "CHGRP   "
    992 
    993     def taskIsDir(self, sRemoteDir):
    994         rc = self.sendMsg('ISDIR', (sRemoteDir,));
    995         if rc is True:
    996             rc = self.recvTrueFalse('ISDIR');
    997         return rc;
    998 
    999     def taskIsFile(self, sRemoteFile):
    1000         rc = self.sendMsg('ISFILE', (sRemoteFile,));
    1001         if rc is True:
    1002             rc = self.recvTrueFalse('ISFILE');
    1003         return rc;
    1004 
    1005     def taskIsSymlink(self, sRemoteSymlink):
    1006         rc = self.sendMsg('ISSYMLNK', (sRemoteSymlink,));
    1007         if rc is True:
    1008             rc = self.recvTrueFalse('ISSYMLNK');
    1009         return rc;
    1010 
    1011     #def "STAT    "
    1012     #def "LSTAT   "
    1013     #def "LIST    "
    1014 
    1015     def taskUploadFile(self, sLocalFile, sRemoteFile):
    1016         #
    1017         # Open the local file (make sure it exist before bothering TXS) and
    1018         # tell TXS that we want to upload a file.
    1019         #
    1020         try:
    1021             oLocalFile = utils.openNoInherit(sLocalFile, 'rb');
    1022         except:
    1023             reporter.errorXcpt('taskUpload: failed to open "%s"' % (sLocalFile));
    1024             return False;
    1025 
    1026         # Common cause with taskUploadStr
    1027         rc = self.taskUploadCommon(oLocalFile, sRemoteFile);
    1028 
    1029         # Cleanup.
    1030         oLocalFile.close();
    1031         return rc;
    1032 
    1033     def taskUploadString(self, sContent, sRemoteFile):
    1034         # Wrap sContent in a file like class.
    1035         class InStringFile(object): # pylint: disable=R0903
    1036             def __init__(self, sContent):
    1037                 self.sContent = sContent;
    1038                 self.off      = 0;
    1039 
    1040             def read(self, cbMax):
    1041                 cbLeft = len(self.sContent) - self.off;
    1042                 if cbLeft == 0:
    1043                     return "";
    1044                 if cbLeft <= cbMax:
    1045                     sRet = self.sContent[self.off:(self.off + cbLeft)];
    1046                 else:
    1047                     sRet = self.sContent[self.off:(self.off + cbMax)];
    1048                 self.off = self.off + len(sRet);
    1049                 return sRet;
    1050 
    1051         oLocalString = InStringFile(sContent);
    1052         return self.taskUploadCommon(oLocalString, sRemoteFile);
    1053 
    1054     def taskUploadCommon(self, oLocalFile, sRemoteFile):
    1055         """Common worker used by taskUploadFile and taskUploadString."""
    1056         # Command + ACK.
    1057         rc = self.sendMsg('PUT FILE', (sRemoteFile,));
    1058         if rc is True:
    1059             rc = self.recvAckLogged('PUT FILE');
    1060         if rc is True:
    1061             #
    1062             # Push data packets until eof.
    1063             #
    1064             uMyCrc32 = zlib.crc32("");
    1065             while True:
    1066                 # Read up to 64 KB of data.
    1067                 try:
    1068                     sRaw = oLocalFile.read(65536);
    1069                 except:
    1070                     rc = None;
    1071                     break;
    1072 
    1073                 # Convert to array - this is silly!
    1074                 abBuf = array.array('B');
    1075                 for i in range(len(sRaw)):
    1076                     abBuf.append(ord(sRaw[i]));
    1077                 sRaw = None;
    1078 
    1079                 # Update the file stream CRC and send it off.
    1080                 uMyCrc32 = zlib.crc32(abBuf, uMyCrc32);
    1081                 if len(abBuf) == 0:
    1082                     rc = self.sendMsg('DATA EOF', (long(uMyCrc32 & 0xffffffff), ));
    1083                 else:
    1084                     rc = self.sendMsg('DATA    ', (long(uMyCrc32 & 0xffffffff), abBuf));
    1085                 if rc is False:
    1086                     break;
    1087 
    1088                 # Wait for the reply.
    1089                 rc = self.recvAck();
    1090                 if rc is not True:
    1091                     if rc is False:
    1092                         reporter.maybeErr(self.fErr, 'taskUpload: transport error waiting for ACK');
    1093                     else:
    1094                         reporter.maybeErr(self.fErr, 'taskUpload: DATA response was %s: %s' % (rc[0], rc[1]));
    1095                         rc = False;
    1096                     break;
    1097 
    1098                 # EOF?
    1099                 if len(abBuf) == 0:
    1100                     break;
    1101 
    1102             # Send ABORT on ACK and I/O errors.
    1103             if rc is None:
    1104                 rc = self.sendMsg('ABORT');
    1105                 if rc is True:
    1106                     self.recvAckLogged('ABORT');
    1107                 rc = False;
    1108         return rc;
    1109 
    1110     def taskDownloadFile(self, sRemoteFile, sLocalFile):
    1111         try:
    1112             oLocalFile = utils.openNoInherit(sLocalFile, 'wb');
    1113         except:
    1114             reporter.errorXcpt('taskDownload: failed to open "%s"' % (sLocalFile));
    1115             return False;
    1116 
    1117         rc = self.taskDownloadCommon(sRemoteFile, oLocalFile);
    1118 
    1119         oLocalFile.close();
    1120         if rc is False:
    1121             try:
    1122                 os.remove(sLocalFile);
    1123             except:
    1124                 reporter.errorXcpt();
    1125         return rc;
    1126 
    1127     def taskDownloadString(self, sRemoteFile):
    1128         # Wrap sContent in a file like class.
    1129         class OutStringFile(object): # pylint: disable=R0903
    1130             def __init__(self):
    1131                 self.asContent = [];
    1132 
    1133             def write(self, sBuf):
    1134                 self.asContent.append(sBuf);
    1135                 return None;
    1136 
    1137         oLocalString = OutStringFile();
    1138         rc = self.taskDownloadCommon(sRemoteFile, oLocalString);
    1139         if rc is True:
    1140             if len(oLocalString.asContent) == 0:
    1141                 rc = '';
    1142             else:
    1143                 rc = ''.join(oLocalString.asContent);
    1144         return rc;
    1145 
    1146     def taskDownloadCommon(self, sRemoteFile, oLocalFile):
    1147         """Common worker for taskDownloadFile and taskDownloadString."""
    1148         rc = self.sendMsg('GET FILE', (sRemoteFile,))
    1149         if rc is True:
    1150             #
    1151             # Process data packets until eof.
    1152             #
    1153             uMyCrc32 = zlib.crc32("");
    1154             while rc is True:
    1155                 cbMsg, sOpcode, abPayload = self.recvReply();
    1156                 if cbMsg is None:
    1157                     reporter.maybeErr(self.fErr, 'taskDownload got 3xNone from recvReply.');
    1158                     rc = None;
    1159                     break;
    1160 
    1161                 # Validate.
    1162                 sOpcode = sOpcode.rstrip();
    1163                 if sOpcode != 'DATA' and sOpcode != 'DATA EOF':
    1164                     reporter.maybeErr(self.fErr, 'taskDownload got a error reply: opcode="%s" details="%s"'
    1165                                       % (sOpcode, getSZ(abPayload, 0, "None")));
    1166                     rc = False;
    1167                     break;
    1168                 if sOpcode == 'DATA' and len(abPayload) < 4:
    1169                     reporter.maybeErr(self.fErr, 'taskDownload got a bad DATA packet: len=%u' % (len(abPayload)));
    1170                     rc = None;
    1171                     break;
    1172                 if sOpcode == 'DATA EOF' and len(abPayload) != 4:
    1173                     reporter.maybeErr(self.fErr, 'taskDownload got a bad EOF packet: len=%u' % (len(abPayload)));
    1174                     rc = None;
    1175                     break;
    1176 
    1177                 # Check the CRC (common for both packets).
    1178                 uCrc32 = getU32(abPayload, 0);
    1179                 if sOpcode == 'DATA':
    1180                     uMyCrc32 = zlib.crc32(abPayload[4:], uMyCrc32);
    1181                 if uCrc32 != (uMyCrc32 & 0xffffffff):
    1182                     reporter.maybeErr(self.fErr, 'taskDownload got a bad CRC: mycrc=%s remotecrc=%s'
    1183                                       % (hex(uMyCrc32), hex(uCrc32)));
    1184                     rc = None;
    1185                     break;
    1186                 if sOpcode == 'DATA EOF':
    1187                     rc = self.sendMsg('ACK');
    1188                     break;
    1189 
    1190                 # Finally, push the data to the file.
    1191                 try:
    1192                     oLocalFile.write(abPayload[4:].tostring());
    1193                 except:
    1194                     reporter.errorXcpt('I/O error writing to "%s"' % (sRemoteFile));
    1195                     rc = None;
    1196                     break;
    1197                 rc = self.sendMsg('ACK');
    1198 
    1199             # Send NACK on validation and I/O errors.
    1200             if rc is None:
    1201                 rc = self.sendMsg('NACK');
    1202                 rc = False;
    1203         return rc;
    1204 
    1205     def taskUnpackFile(self, sRemoteFile, sRemoteDir):
    1206         rc = self.sendMsg('UNPKFILE', (sRemoteFile, sRemoteDir));
    1207         if rc is True:
    1208             rc = self.recvAckLogged('UNPKFILE');
    1209         return rc;
    1210 
    1211     # pylint: enable=C0111
    1212 
    1213745
    1214746    #
     
    1269801        return self.asyncToSync(self.asyncDisconnect, cMsTimeout, fIgnoreErrors);
    1270802
    1271     def asyncUuid(self, cMsTimeout = 30000, fIgnoreErrors = False):
    1272         """
    1273         Initiates a task for getting the TXS UUID.
    1274 
    1275         Returns True on success, False on failure (logged).
    1276 
    1277         The task returns UUID string (in {}) on success and False on failure.
    1278         """
    1279         return self.startTask(cMsTimeout, fIgnoreErrors, "bye", self.taskUuid);
    1280 
    1281     def syncUuid(self, cMsTimeout = 30000, fIgnoreErrors = False):
    1282         """Synchronous version."""
    1283         return self.asyncToSync(self.asyncUuid, cMsTimeout, fIgnoreErrors);
    1284 
    1285803    #
    1286     # Public methods - execution.
     804    # Public methods - gadget API
    1287805    #
    1288806
    1289     def asyncExecEx(self, sExecName, asArgs = (), asAddEnv = (), # pylint: disable=R0913
    1290                     oStdIn = None, oStdOut = None, oStdErr = None, oTestPipe = None,
    1291                     sAsUser = "", cMsTimeout = 3600000, fIgnoreErrors = False):
    1292         """
    1293         Initiates a exec process task.
    1294 
    1295         Returns True on success, False on failure (logged).
    1296 
    1297         The task returns True if the process exited normally with status code 0.
    1298         The task returns None if on failure prior to executing the process, and
    1299         False if the process exited with a different status or in an abnormal
    1300         manner.  Both None and False are logged of course and further info can
    1301         also be obtained by getLastReply().
    1302 
    1303         The oStdIn, oStdOut, oStdErr and oTestPipe specifiy how to deal with
    1304         these streams.  If None, no special action is taken and the output goes
    1305         to where ever the TXS sends its output, and ditto for input.
    1306             - To send to / read from the bitbucket, pass '/dev/null'.
    1307             - To redirect to/from a file, just specify the remote filename.
    1308             - To append to a file use '>>' followed by the remote filename.
    1309             - To pipe the stream to/from the TXS, specify a file like
    1310               object.  For StdIn a non-blocking read() method is required. For
    1311               the other a write() method is required.  Watch out for deadlock
    1312               conditions between StdIn and StdOut/StdErr/TestPipe piping.
    1313         """
    1314         return self.startTask(cMsTimeout, fIgnoreErrors, "exec", self.taskExecEx,
    1315                               (sExecName, long(0), asArgs, asAddEnv, oStdIn,
    1316                                oStdOut, oStdErr, oTestPipe, sAsUser));
    1317 
    1318     def syncExecEx(self, sExecName, asArgs = (), asAddEnv = (), # pylint: disable=R0913
    1319                    oStdIn = '/dev/null', oStdOut = '/dev/null',
    1320                    oStdErr = '/dev/null', oTestPipe = '/dev/null',
    1321                    sAsUser = '', cMsTimeout = 3600000, fIgnoreErrors = False):
    1322         """Synchronous version."""
    1323         return self.asyncToSync(self.asyncExecEx, sExecName, asArgs, asAddEnv, oStdIn, oStdOut, \
    1324                                                   oStdErr, oTestPipe, sAsUser, cMsTimeout, fIgnoreErrors);
    1325 
    1326     def asyncExec(self, sExecName, asArgs = (), asAddEnv = (), sAsUser = "", fWithTestPipe = True, sPrefix = '', \
    1327                   cMsTimeout = 3600000, fIgnoreErrors = False):
    1328         """
    1329         Initiates a exec process test task.
    1330 
    1331         Returns True on success, False on failure (logged).
    1332 
    1333         The task returns True if the process exited normally with status code 0.
    1334         The task returns None if on failure prior to executing the process, and
    1335         False if the process exited with a different status or in an abnormal
    1336         manner.  Both None and False are logged of course and further info can
    1337         also be obtained by getLastReply().
    1338 
    1339         Standard in is taken from /dev/null.  While both standard output and
    1340         standard error goes directly to reporter.log().  The testpipe is piped
    1341         to reporter.xxxx.
    1342         """
    1343 
    1344         sStdIn    = '/dev/null';
    1345         oStdOut   = reporter.FileWrapper('%sstdout' % sPrefix);
    1346         oStdErr   = reporter.FileWrapper('%sstderr' % sPrefix);
    1347         if fWithTestPipe:   oTestPipe = reporter.FileWrapperTestPipe();
    1348         else:               oTestPipe = '/dev/null';
    1349 
    1350         return self.startTask(cMsTimeout, fIgnoreErrors, "exec", self.taskExecEx,
    1351                               (sExecName, long(0), asArgs, asAddEnv, sStdIn, oStdOut, oStdErr, oTestPipe, sAsUser));
    1352 
    1353     def syncExec(self, sExecName, asArgs = (), asAddEnv = (), sAsUser = '', fWithTestPipe = True, sPrefix = '',
    1354                  cMsTimeout = 3600000, fIgnoreErrors = False):
    1355         """Synchronous version."""
    1356         return self.asyncToSync(self.asyncExec, sExecName, asArgs, asAddEnv, sAsUser, fWithTestPipe, sPrefix, \
    1357             cMsTimeout, fIgnoreErrors);
    1358 
    1359     #
    1360     # Public methods - file system
    1361     #
    1362 
    1363     def asyncReboot(self, cMsTimeout = 30000, fIgnoreErrors = False):
    1364         """
    1365         Initiates a reboot task.
    1366 
    1367         Returns True on success, False on failure (logged).
    1368 
    1369         The task returns True on success, False on failure (logged).  The
    1370         session will be disconnected on successful task completion.
    1371         """
    1372         return self.startTask(cMsTimeout, fIgnoreErrors, "reboot", self.taskReboot, ());
    1373 
    1374     def syncReboot(self, cMsTimeout = 30000, fIgnoreErrors = False):
    1375         """Synchronous version."""
    1376         return self.asyncToSync(self.asyncReboot, cMsTimeout, fIgnoreErrors);
    1377 
    1378     def asyncShutdown(self, cMsTimeout = 30000, fIgnoreErrors = False):
    1379         """
    1380         Initiates a shutdown task.
    1381 
    1382         Returns True on success, False on failure (logged).
    1383 
    1384         The task returns True on success, False on failure (logged).
    1385         """
    1386         return self.startTask(cMsTimeout, fIgnoreErrors, "shutdown", self.taskShutdown, ());
    1387 
    1388     def syncShutdown(self, cMsTimeout = 30000, fIgnoreErrors = False):
    1389         """Synchronous version."""
    1390         return self.asyncToSync(self.asyncShutdown, cMsTimeout, fIgnoreErrors);
    1391 
    1392 
    1393     #
    1394     # Public methods - file system
    1395     #
    1396 
    1397     def asyncMkDir(self, sRemoteDir, fMode = 0700, cMsTimeout = 30000, fIgnoreErrors = False):
    1398         """
    1399         Initiates a mkdir task.
    1400 
    1401         Returns True on success, False on failure (logged).
    1402 
    1403         The task returns True on success, False on failure (logged).
    1404         """
    1405         return self.startTask(cMsTimeout, fIgnoreErrors, "mkDir", self.taskMkDir, (sRemoteDir, long(fMode)));
    1406 
    1407     def syncMkDir(self, sRemoteDir, fMode = 0700, cMsTimeout = 30000, fIgnoreErrors = False):
    1408         """Synchronous version."""
    1409         return self.asyncToSync(self.asyncMkDir, sRemoteDir, long(fMode), cMsTimeout, fIgnoreErrors);
    1410 
    1411     def asyncMkDirPath(self, sRemoteDir, fMode = 0700, cMsTimeout = 30000, fIgnoreErrors = False):
    1412         """
    1413         Initiates a mkdir -p task.
    1414 
    1415         Returns True on success, False on failure (logged).
    1416 
    1417         The task returns True on success, False on failure (logged).
    1418         """
    1419         return self.startTask(cMsTimeout, fIgnoreErrors, "mkDirPath", self.taskMkDirPath, (sRemoteDir, long(fMode)));
    1420 
    1421     def syncMkDirPath(self, sRemoteDir, fMode = 0700, cMsTimeout = 30000, fIgnoreErrors = False):
    1422         """Synchronous version."""
    1423         return self.asyncToSync(self.asyncMkDirPath, sRemoteDir, long(fMode), cMsTimeout, fIgnoreErrors);
    1424 
    1425     def asyncMkSymlink(self, sLinkTarget, sLink, cMsTimeout = 30000, fIgnoreErrors = False):
    1426         """
    1427         Initiates a symlink task.
    1428 
    1429         Returns True on success, False on failure (logged).
    1430 
    1431         The task returns True on success, False on failure (logged).
    1432         """
    1433         return self.startTask(cMsTimeout, fIgnoreErrors, "mkSymlink", self.taskMkSymlink, (sLinkTarget, sLink));
    1434 
    1435     def syncMkSymlink(self, sLinkTarget, sLink, cMsTimeout = 30000, fIgnoreErrors = False):
    1436         """Synchronous version."""
    1437         return self.asyncToSync(self.asyncMkSymlink, sLinkTarget, sLink, cMsTimeout, fIgnoreErrors);
    1438 
    1439     def asyncRmDir(self, sRemoteDir, cMsTimeout = 30000, fIgnoreErrors = False):
    1440         """
    1441         Initiates a rmdir task.
    1442 
    1443         Returns True on success, False on failure (logged).
    1444 
    1445         The task returns True on success, False on failure (logged).
    1446         """
    1447         return self.startTask(cMsTimeout, fIgnoreErrors, "rmDir", self.taskRmDir, (sRemoteDir,));
    1448 
    1449     def syncRmDir(self, sRemoteDir, cMsTimeout = 30000, fIgnoreErrors = False):
    1450         """Synchronous version."""
    1451         return self.asyncToSync(self.asyncRmDir, sRemoteDir, cMsTimeout, fIgnoreErrors);
    1452 
    1453     def asyncRmFile(self, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1454         """
    1455         Initiates a rmfile task.
    1456 
    1457         Returns True on success, False on failure (logged).
    1458 
    1459         The task returns True on success, False on failure (logged).
    1460         """
    1461         return self.startTask(cMsTimeout, fIgnoreErrors, "rmFile", self.taskRmFile, (sRemoteFile,));
    1462 
    1463     def syncRmFile(self, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1464         """Synchronous version."""
    1465         return self.asyncToSync(self.asyncRmFile, sRemoteFile, cMsTimeout, fIgnoreErrors);
    1466 
    1467     def asyncRmSymlink(self, sRemoteSymlink, cMsTimeout = 30000, fIgnoreErrors = False):
    1468         """
    1469         Initiates a rmsymlink task.
    1470 
    1471         Returns True on success, False on failure (logged).
    1472 
    1473         The task returns True on success, False on failure (logged).
    1474         """
    1475         return self.startTask(cMsTimeout, fIgnoreErrors, "rmSymlink", self.taskRmSymlink, (sRemoteSymlink,));
    1476 
    1477     def syncRmSymlink(self, sRemoteSymlink, cMsTimeout = 30000, fIgnoreErrors = False):
    1478         """Synchronous version."""
    1479         return self.asyncToSync(self.asyncRmSymlink, sRemoteSymlink, cMsTimeout, fIgnoreErrors);
    1480 
    1481     def asyncRmTree(self, sRemoteTree, cMsTimeout = 30000, fIgnoreErrors = False):
    1482         """
    1483         Initiates a rmtree task.
    1484 
    1485         Returns True on success, False on failure (logged).
    1486 
    1487         The task returns True on success, False on failure (logged).
    1488         """
    1489         return self.startTask(cMsTimeout, fIgnoreErrors, "rmTree", self.taskRmTree, (sRemoteTree,));
    1490 
    1491     def syncRmTree(self, sRemoteTree, cMsTimeout = 30000, fIgnoreErrors = False):
    1492         """Synchronous version."""
    1493         return self.asyncToSync(self.asyncRmTree, sRemoteTree, cMsTimeout, fIgnoreErrors);
    1494 
    1495     #def "CHMOD   "
    1496     #def "CHOWN   "
    1497     #def "CHGRP   "
    1498 
    1499     def asyncIsDir(self, sRemoteDir, cMsTimeout = 30000, fIgnoreErrors = False):
    1500         """
    1501         Initiates a is-dir query task.
    1502 
    1503         Returns True on success, False on failure (logged).
    1504 
    1505         The task returns True if it's a directory, False if it isn't, and
    1506         None on error (logged).
    1507         """
    1508         return self.startTask(cMsTimeout, fIgnoreErrors, "isDir", self.taskIsDir, (sRemoteDir,));
    1509 
    1510     def syncIsDir(self, sRemoteDir, cMsTimeout = 30000, fIgnoreErrors = False):
    1511         """Synchronous version."""
    1512         return self.asyncToSync(self.asyncIsDir, sRemoteDir, cMsTimeout, fIgnoreErrors);
    1513 
    1514     def asyncIsFile(self, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1515         """
    1516         Initiates a is-file query task.
    1517 
    1518         Returns True on success, False on failure (logged).
    1519 
    1520         The task returns True if it's a file, False if it isn't, and None on
    1521         error (logged).
    1522         """
    1523         return self.startTask(cMsTimeout, fIgnoreErrors, "isFile", self.taskIsFile, (sRemoteFile,));
    1524 
    1525     def syncIsFile(self, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1526         """Synchronous version."""
    1527         return self.asyncToSync(self.asyncIsFile, sRemoteFile, cMsTimeout, fIgnoreErrors);
    1528 
    1529     def asyncIsSymlink(self, sRemoteSymlink, cMsTimeout = 30000, fIgnoreErrors = False):
    1530         """
    1531         Initiates a is-symbolic-link query task.
    1532 
    1533         Returns True on success, False on failure (logged).
    1534 
    1535         The task returns True if it's a symbolic linke, False if it isn't, and
    1536         None on error (logged).
    1537         """
    1538         return self.startTask(cMsTimeout, fIgnoreErrors, "isSymlink", self.taskIsSymlink, (sRemoteSymlink,));
    1539 
    1540     def syncIsSymlink(self, sRemoteSymlink, cMsTimeout = 30000, fIgnoreErrors = False):
    1541         """Synchronous version."""
    1542         return self.asyncToSync(self.asyncIsSymlink, sRemoteSymlink, cMsTimeout, fIgnoreErrors);
    1543 
    1544     #def "STAT    "
    1545     #def "LSTAT   "
    1546     #def "LIST    "
    1547 
    1548     def asyncUploadFile(self, sLocalFile, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1549         """
    1550         Initiates a download query task.
    1551 
    1552         Returns True on success, False on failure (logged).
    1553 
    1554         The task returns True on success, False on failure (logged).
    1555         """
    1556         return self.startTask(cMsTimeout, fIgnoreErrors, "upload", self.taskUploadFile, (sLocalFile, sRemoteFile));
    1557 
    1558     def syncUploadFile(self, sLocalFile, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1559         """Synchronous version."""
    1560         return self.asyncToSync(self.asyncUploadFile, sLocalFile, sRemoteFile, cMsTimeout, fIgnoreErrors);
    1561 
    1562     def asyncUploadString(self, sContent, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1563         """
    1564         Initiates a upload string task.
    1565 
    1566         Returns True on success, False on failure (logged).
    1567 
    1568         The task returns True on success, False on failure (logged).
    1569         """
    1570         return self.startTask(cMsTimeout, fIgnoreErrors, "uploadString", self.taskUploadString, (sContent, sRemoteFile));
    1571 
    1572     def syncUploadString(self, sContent, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1573         """Synchronous version."""
    1574         return self.asyncToSync(self.asyncUploadString, sContent, sRemoteFile, cMsTimeout, fIgnoreErrors);
    1575 
    1576     def asyncDownloadFile(self, sRemoteFile, sLocalFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1577         """
    1578         Initiates a download file task.
    1579 
    1580         Returns True on success, False on failure (logged).
    1581 
    1582         The task returns True on success, False on failure (logged).
    1583         """
    1584         return self.startTask(cMsTimeout, fIgnoreErrors, "downloadFile", self.taskDownloadFile, (sRemoteFile, sLocalFile));
    1585 
    1586     def syncDownloadFile(self, sRemoteFile, sLocalFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1587         """Synchronous version."""
    1588         return self.asyncToSync(self.asyncDownloadFile, sRemoteFile, sLocalFile, cMsTimeout, fIgnoreErrors);
    1589 
    1590     def asyncDownloadString(self, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1591         """
    1592         Initiates a download string task.
    1593 
    1594         Returns True on success, False on failure (logged).
    1595 
    1596         The task returns a byte string on success, False on failure (logged).
    1597         """
    1598         return self.startTask(cMsTimeout, fIgnoreErrors, "downloadString", self.taskDownloadString, (sRemoteFile,));
    1599 
    1600     def syncDownloadString(self, sRemoteFile, cMsTimeout = 30000, fIgnoreErrors = False):
    1601         """Synchronous version."""
    1602         return self.asyncToSync(self.asyncDownloadString, sRemoteFile, cMsTimeout, fIgnoreErrors);
    1603 
    1604     def asyncUnpackFile(self, sRemoteFile, sRemoteDir, cMsTimeout = 30000, fIgnoreErrors = False):
    1605         """
    1606         Initiates a unpack file task.
    1607 
    1608         Returns True on success, False on failure (logged).
    1609 
    1610         The task returns True on success, False on failure (logged).
    1611         """
    1612         return self.startTask(cMsTimeout, fIgnoreErrors, "unpackFile", self.taskUnpackFile, \
    1613                               (sRemoteFile, sRemoteDir));
    1614 
    1615     def syncUnpackFile(self, sRemoteFile, sRemoteDir, cMsTimeout = 30000, fIgnoreErrors = False):
    1616         """Synchronous version."""
    1617         return self.asyncToSync(self.asyncUnpackFile, sRemoteFile, sRemoteDir, cMsTimeout, fIgnoreErrors);
     807    def
    1618808
    1619809
    1620810class TransportTcp(TransportBase):
    1621811    """
    1622     TCP transport layer for the TXS client session class.
    1623     """
    1624 
    1625     def __init__(self, sHostname, uPort, fReversedSetup):
     812    TCP transport layer for the UTS client session class.
     813    """
     814
     815    def __init__(self, sHostname, uPort):
    1626816        """
    1627817        Save the parameters. The session will call us back to make the
     
    1630820        TransportBase.__init__(self, utils.getCallerName());
    1631821        self.sHostname        = sHostname;
    1632         self.fReversedSetup   = fReversedSetup;
    1633         self.uPort            = uPort if uPort is not None else 5042 if fReversedSetup is False else 5048;
     822        self.uPort            = uPort if uPort is not None else 6042;
    1634823        self.oSocket          = None;
    1635824        self.oWakeupW         = None;
     
    1641830
    1642831    def toString(self):
    1643         return '<%s sHostname=%s, fReversedSetup=%s, uPort=%s, oSocket=%s,'\
     832        return '<%s sHostname=%s, uPort=%s, oSocket=%s,'\
    1644833               ' fConnectCanceled=%s, fIsConnecting=%s, oCv=%s, abReadAhead=%s>' \
    1645              % (TransportBase.toString(self), self.sHostname, self.fReversedSetup, self.uPort, self.oSocket,
     834             % (TransportBase.toString(self), self.sHostname, self.uPort, self.oSocket,
    1646835                self.fConnectCanceled, self.fIsConnecting, self.oCv, self.abReadAhead);
    1647836
     
    1732921        self.oCv.release();
    1733922
    1734     def _connectAsServer(self, oSocket, oWakeupR, cMsTimeout):
    1735         """ Connects to the TXS server as server, i.e. the reversed setup. """
    1736         assert(self.fReversedSetup);
    1737 
    1738         reporter.log2('TransportTcp::_connectAsServer: oSocket=%s, cMsTimeout=%u' % (oSocket, cMsTimeout));
    1739 
    1740         # Workaround for bind() failure...
    1741         try:
    1742             oSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1);
    1743         except:
    1744             reporter.errorXcpt('socket.listen(1) failed');
    1745             return None;
    1746 
    1747         # Bind the socket and make it listen.
    1748         try:
    1749             oSocket.bind((self.sHostname, self.uPort));
    1750         except:
    1751             reporter.errorXcpt('socket.bind((%s,%s)) failed' % (self.sHostname, self.uPort));
    1752             return None;
    1753         try:
    1754             oSocket.listen(1);
    1755         except:
    1756             reporter.errorXcpt('socket.listen(1) failed');
    1757             return None;
    1758 
    1759         # Accept connections.
    1760         oClientSocket = None;
    1761         tClientAddr   = None;
    1762         try:
    1763             (oClientSocket, tClientAddr) = oSocket.accept();
    1764         except socket.error, e:
    1765             if not self.__isInProgressXcpt(e):
    1766                 raise;
    1767 
    1768             # Do the actual waiting.
    1769             reporter.log2('TransportTcp::accept: operation in progress (%s)...' % (e,));
    1770             try:
    1771                 select.select([oSocket, oWakeupR], [], [oSocket, oWakeupR], cMsTimeout / 1000.0);
    1772             except socket.error, e:
    1773                 if e[0] != errno.EBADF  or  not self.fConnectCanceled:
    1774                     raise;
    1775                 reporter.log('socket.select() on accept was canceled');
    1776                 return None;
    1777             except:
    1778                 reporter.logXcpt('socket.select() on accept');
    1779 
    1780             # Try accept again.
    1781             try:
    1782                 (oClientSocket, tClientAddr) = oSocket.accept();
    1783             except socket.error, e:
    1784                 if not self.__isInProgressXcpt(e):
    1785                     if e[0] != errno.EBADF  or  not self.fConnectCanceled:
    1786                         raise;
    1787                     reporter.log('socket.accept() was canceled');
    1788                     return None;
    1789                 reporter.log('socket.accept() timed out');
    1790                 return False;
    1791             except:
    1792                 reporter.errorXcpt('socket.accept() failed');
    1793                 return None;
    1794         except:
    1795             reporter.errorXcpt('socket.accept() failed');
    1796             return None;
    1797 
    1798         # Store the connected socket and throw away the server socket.
    1799         self.oCv.acquire();
    1800         if not self.fConnectCanceled:
    1801             self.oSocket.close();
    1802             self.oSocket = oClientSocket;
    1803             self.sHostname = "%s:%s" % (tClientAddr[0], tClientAddr[1]);
    1804         self.oCv.release();
    1805         return True;
    1806 
    1807923    def _connectAsClient(self, oSocket, oWakeupR, cMsTimeout):
    1808         """ Connects to the TXS server as client. """
    1809         assert(not self.fReversedSetup);
     924        """ Connects to the UTS server as client. """
    1810925
    1811926        # Connect w/ timeouts.
     
    1884999            if oWakeupR is None:
    18851000                oWakeupR = oSocket; # Avoid select failure.
    1886             if self.fReversedSetup:
    1887                 rc = self._connectAsServer(oSocket, oWakeupR, cMsTimeout);
    1888             else:
    1889                 rc = self._connectAsClient(oSocket, oWakeupR, cMsTimeout);
     1001            rc = self._connectAsClient(oSocket, oWakeupR, cMsTimeout);
    18901002            oSocket = None;
    18911003
     
    20821194
    20831195
    2084 def openTcpSession(cMsTimeout, sHostname, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
    2085     """
    2086     Opens a connection to a Test Execution Service via TCP, given its name.
    2087     """
    2088     reporter.log2('openTcpSession(%s, %s, %s, %s, %s)' % \
    2089                   (cMsTimeout, sHostname, uPort, fReversedSetup, cMsIdleFudge));
    2090     try:
    2091         oTransport = TransportTcp(sHostname, uPort, fReversedSetup);
    2092         oSession = Session(oTransport, cMsTimeout, cMsIdleFudge);
    2093     except:
    2094         reporter.errorXcpt(None, 15);
    2095         return None;
    2096     return oSession;
    2097 
    2098 
    2099 def tryOpenTcpSession(cMsTimeout, sHostname, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
    2100     """
    2101     Tries to open a connection to a Test Execution Service via TCP, given its name.
    2102 
    2103     This differs from openTcpSession in that it won't log a connection failure
    2104     as an error.
    2105     """
    2106     try:
    2107         oTransport = TransportTcp(sHostname, uPort, fReversedSetup);
    2108         oSession = Session(oTransport, cMsTimeout, cMsIdleFudge, fTryConnect = True);
    2109     except:
    2110         reporter.errorXcpt(None, 15);
    2111         return None;
    2112     return oSession;
    2113 
     1196class UsbGadget(object):
     1197    """
     1198    USB Gadget control class using the USBT Test Service to talk to the external
     1199    board behaving like a USB device.
     1200    """
     1201
     1202    def __init__(self):
     1203        self.oUtsSession    = None;
     1204        self.sImpersonation = g_ksGadgetImpersonationInvalid;
     1205        self.sGadgetType    = g_ksGadgetTypeInvalid;
     1206        self.idGadget       = None;
     1207
     1208    def _clearImpersonation(self):
     1209        """
     1210        Removes the current impersonation of the gadget.
     1211        """
     1212        fRc = True;
     1213
     1214        if self.idGadget is not None:
     1215            fRc = self.oUtsSession.syncGadgetDestroy(self.idGadget);
     1216
     1217        return fRc;
     1218
     1219    def disconnectUsb(self):
     1220        """
     1221        Disconnects the USB gadget from the host. (USB connection not network
     1222        connection used for control)
     1223        """
     1224        return self.oUtsSession.syncGadgetDisconnect(self.idGadget);
     1225
     1226    def connectUsb(self):
     1227        """
     1228        Connect the USB gadget to the host.
     1229        """
     1230        return self.oUtsSession.syncGadgetConnect(self.idGadget);
     1231
     1232    def impersonate(self, sImpersonation):
     1233        """
     1234        Impersonate a given device.
     1235        """
     1236
     1237        # Clear any previous impersonation
     1238        self._clearImpersonation();
     1239        self.sImpersonation = sImpersonation;
     1240
     1241        fRc = False;
     1242        if sImpersonation == g_ksGadgetImpersonationTest:
     1243            fRc = self.oUtsSession.syncGadgetCreate(g_kiGadgetTypeTest);
     1244        else:
     1245            reporter.log('Invalid or unsupported impersonation');
     1246
     1247        return fRc;
     1248
     1249    def connectTo(self, cMsTimeout, sHostname, uPort = None):
     1250        """
     1251        Connects to the specified target device.
     1252        Returns True on Success.
     1253        Returns False otherwise.
     1254        """
     1255        fRc = True;
     1256
     1257        reporter.log2('openTcpSession(%s, %s, %s, %s)' % \
     1258                      (cMsTimeout, sHostname, uPort, cMsIdleFudge));
     1259        try:
     1260            oTransport = TransportTcp(sHostname, uPort);
     1261            self.oUtsSession = Session(oTransport, cMsTimeout, cMsIdleFudge);
     1262
     1263            if self.oUtsSession is not None:
     1264                fDone = self.oUtsSession.waitForTask(30*1000);
     1265                print 'connect: waitForTask -> %s, result %s' % (fDone, self.oUtsSession.getResult());
     1266                if fDone is True and self.oUtsSession.isSuccess():
     1267                    fRc = True;
     1268                else:
     1269                    fRc = False;
     1270            else:
     1271                fRc = False;
     1272
     1273            if fRc:
     1274                fRc = self._prepareGadget();
     1275        except:
     1276            reporter.errorXcpt(None, 15);
     1277            return False;
     1278
     1279        return fRc;
     1280
     1281    def disconnectFrom(self):
     1282        """
     1283        Disconnects from the target device.
     1284        """
     1285        fRc = True;
     1286
     1287        self._clearImpersonation();
     1288        self._cleanupGadget();
     1289        if self.oUtsSession is not None:
     1290            fRc = self.oUtsSession.syncDisconnect();
     1291
     1292        return fRc;
     1293
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette