'Receives and processes data coming from the remote machine.
The incoming `data\' is dispatched depending on the current protocol
state and whether we are the client or the server.  The data is either
payload or authentication data.'

def receivedDownstream(self, data):

    if (self.weAreServer and (self.protoState == const.ST_AUTH_FAILED)):
        self.drainedHandshake += len(data)
        data.drain(len(data))
        if (self.drainedHandshake > self.srvState.closingThreshold):
            self.circuit.close()
            return
    elif (self.weAreServer and (self.protoState == const.ST_WAIT_FOR_AUTH)):
        if self.receiveTicket(data):
            self.sendTicketAndSeed()
        elif self.uniformdh.receivePublicKey(data, self.deriveSecrets, self.srvState):
            handshakeMsg = self.uniformdh.createHandshake(srvState=self.srvState)
            self.circuit.downstream.write(handshakeMsg)
            self.protoState = const.ST_CONNECTED
            self.sendTicketAndSeed()
        elif (len(data) > const.MAX_HANDSHAKE_LENGTH):
            self.protoState = const.ST_AUTH_FAILED
            self.drainedHandshake = len(data)
            data.drain(self.drainedHandshake)
            return
        else:
            return
    elif (self.weAreClient and (self.protoState == const.ST_WAIT_FOR_AUTH)):
        if (not self.uniformdh.receivePublicKey(data, self.deriveSecrets)):
            return
        self.protoState = const.ST_CONNECTED
        self.flushSendBuffer()
    if (self.protoState == const.ST_CONNECTED):
        self.processMessages(data.read())
