class MiddlewareActor extends AnyRef
MiddlewareActor sits between the raw UDP socket and the "main" actors (either login or session) and handles crypto and control packets. This means it sets up cryptography, it decodes incoming packets, it encodes, bundles and splits outgoing packets, it handles things like requesting/resending lost packets and more.
- Source
- MiddlewareActor.scala
- Alphabetic
- By Inheritance
- MiddlewareActor
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Instance Constructors
- new MiddlewareActor(context: ActorContext[Command], socket: ActorRef[Command], sender: InetSocketAddress, next: (ActorRef[Command], InetSocketAddress, String) => Behavior[PlanetSidePacket], connectionId: String)
Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##: Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- var acceptedSmpSubslot: Int
- def active(): Behavior[Command]
- def activeNormal(packet: PlanetSidePacket, sequence: Int): Unit
Properly handle the newly-arrived packet based on its sequence number.
Properly handle the newly-arrived packet based on its sequence number. If the packet is in the proper order, or is considered old, by its sequence number, act on the packet immediately. If the sequence if higher than the next one expected, indicating that some packets may have been missed, put that packet to the side and active a resolution queue.
- packet
the packet
- sequence
the sequence number obtained from the packet
- def activeWithReordering(packet: PlanetSidePacket, sequence: Int): Unit
Properly handle the newly-arrived packet based on its sequence number, with an ongoing resolution queue for managing out of sequence packets.
Properly handle the newly-arrived packet based on its sequence number, with an ongoing resolution queue for managing out of sequence packets. If the packet is in the proper order, or is considered old, by its sequence number, act on the packet immediately. If the packet is considered a packet that was expected in the past, attempt to clear it from the queue and test the resolution queue for further work. If the sequence if higher than the next one expected, indicating that some packets may have been missed, add it to the resolution queue. Finally, act on the state of the resolution queue.
- packet
the packet
- sequence
the sequence number obtained from the packet
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- def askForMissingSubslots(): Unit
Start making requests for missing
SlotedMetaPacketsif no prior requests were prepared.Start making requests for missing
SlotedMetaPacketsif no prior requests were prepared. Start the scheduled task and handle the dispatched requests.- See also
inSubslotsMissingRequestFuncsinSubslotsMissingRequestsFinishedRelatedA
- var clientNonce: Long
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native()
- def connectionClose(): Behavior[Command]
End client-server ops.
End client-server ops. End messaging capabilities.
- var crypto: Option[CryptoCoding]
- def cryptoFinish(dh: DiffieHellman, clientChallenge: ByteVector, serverChallenge: ByteVector): Behavior[Command]
- def cryptoSetup(): Behavior[Command]
- implicit val ec: ExecutionContextExecutor
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- implicit val executor: ExecutionContext
- def finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable])
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- def in(packet: Attempt[PlanetSidePacket]): Unit
- def in(packet: PlanetSidePacket): Behavior[Command]
Handle incoming packet
- def inReorderQueueTest(): Unit
If the inbound reorder queue is empty, do no more work on it until work is available.
If the inbound reorder queue is empty, do no more work on it until work is available. Otherwise, do work on whatever is at the front of the queue, and do not test again until explicitly requested. Test the queue for more contents after removing content from it.
- val inReorderTimeout: FiniteDuration
how long packets that are out of sequential order wait for the missing sequence before being expedited (ms)
- var inSequence: Int
Latest incoming sequence number
- var inSubslot: Int
Latest incoming subslot number
- val inSubslotMissingDelay: FiniteDuration
how long to wait between repeated requests for packets with known missing subslot numbers (ms)
- val inSubslotMissingNumberOfAttempts: Int
how many time to repeat the request for a packet with a known missing subslot number
- def inSubslotMissingRequests(slot: Int, subslot: Int, inner: ByteVector): Unit
What to do with an inbound
SlottedMetaPacketcontrol packet when the subslots are in disarray.What to do with an inbound
SlottedMetaPacketcontrol packet when the subslots are in disarray. Whenever a subslot arrives prior to the current highest, removing that subslot from the request list is possible. If the proper next subslot arrives, proceeding like normal is fine. Do not, however, send anyResultBconfirmations until no more requests are outstanding.- slot
the SMP slot (related to the opcode)
- subslot
the SMP subslot (related to the expected order of packets)
- inner
the contents of this SMP
- See also
ininSubslotsMissingRequestsFinishedPacketCoding.decodePacket
- def inSubslotNotMissing(slot: Int, subslot: Int, inner: ByteVector): Unit
What to do with a
SlottedMetaPacketcontrol packet normally.What to do with a
SlottedMetaPacketcontrol packet normally. The typical approach, when the subslot is the expected next number, is to merely receive the packet and dispatch a confirmation. When the subslot is farther ahead of what is expected, requests need to be logged for the missing subslots.- slot
the SMP slot (related to the opcode)
- subslot
the SMP subslot (related to the expected order of packets)
- inner
the contents of this SMP
- See also
askForMissingSubslotsininSubslotMissingRequestsPacketCoding.decodePacketRelatedB
- val inSubslotsMissing: Map[Int, Int]
List of missing subslot numbers and attempts counter
- def inSubslotsMissingRequestsFinished(slot: Int = 0): Unit
If there are no more requests for missing subslots, resume normal operations when acting upon inbound
SlottedMetaPacketpackets.If there are no more requests for missing subslots, resume normal operations when acting upon inbound
SlottedMetaPacketpackets.- slot
the optional slot to report the "first"
RelatedBin a "while"
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- val nextActor: ActorRef[PlanetSidePacket]
- def nextSequence: Int
Increment the outbound sequence number.
Increment the outbound sequence number. The previous sequence number is returned. The fidelity of the sequence field in packets is 16 bits, so wrap back to 0 after 65535.
- var nextSmpIndex: Int
- def nextSubslot: Int
Increment the outbound subslot number.
Increment the outbound subslot number. The previous subslot number is returned. The fidelity of the subslot field in
SlottedMetapacket's is 16 bits, so wrap back to 0 after 65535. - final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- val onSignal: PartialFunction[(ActorContext[Command], Signal), Behavior[Command]]
- def out(packet: PlanetSidePacket): Unit
Handle outgoing packet
- val outQueue: Queue[(PlanetSidePacket, BitVector)]
Queue of outgoing packets used for bundling and splitting
- val outQueueBundled: Queue[PlanetSidePacket]
Queue of outgoing packets ready for sending
- var outSequence: Int
Latest outbound sequence number
- var outSubslot: Int
Latest outbound subslot number; the current subslot is one less than this number
- var packetProcessor: Cancellable
Timer that handles the bundling and throttling of outgoing packets and resolves disorganized inbound packets
- val packetProcessorDelay: FiniteDuration
Delay between runs of the packet bundler/resolver timer (ms); 250ms per network update (client upstream), so 10 runs of this bundling code every update
- val packetsBundledByThemselves: List[(PlanetSidePacket) => Boolean]
Do not bundle these packets together with other packets
- val preparedSlottedMetaPackets: Array[SlottedMetaPacket]
History of created
SlottedMetaPackets.History of created
SlottedMetaPackets. In case the client does not register receiving a packet by checking against packet subslot index numbers, it will dispatch aRelatedApacket, and the server will hopefully locate the packet where it has been backlogged. The client will also dispatch aRelatedBpacket to indicate the packet with the highest subslot received. All packets with subslots less than that number have been received or will no longer be requested. The client and server supposedly maintain reciprocating mechanisms. - def processInReorderQueue(): Unit
Examine inbound packets that need to be reordered by sequence number and pass all packets that are now in the correct order and pass packets that have been kept waiting for too long in the queue.
Examine inbound packets that need to be reordered by sequence number and pass all packets that are now in the correct order and pass packets that have been kept waiting for too long in the queue. Set the recorded inbound sequence number to belong to the greatest packet removed from the queue.
- See also
processInReorderQueueTimeoutOnly
- def processInReorderQueueTimeoutOnly(): Unit
Examine inbound packets that need to be reordered by sequence number and pass packets that have been kept waiting for too long in the queue.
Examine inbound packets that need to be reordered by sequence number and pass packets that have been kept waiting for too long in the queue. Set the recorded inbound sequence number to belong to the greatest packet removed from the queue. This may run during the scheduled check on the in-order queue after the outbound bundling process.
- def processOutQueueBundle(): Unit
Outbound packets that have not been caught by other guards need to be bundled and placed into
SlottedMetaPacketmessages.Outbound packets that have not been caught by other guards need to be bundled and placed into
SlottedMetaPacketmessages. Multiple packets in one bundle have to be placed into aMultiPacketExmessage wrapper before being placed into theSlottedMetaPacket. Packets that are too big for the MTU must go on to be split into smaller portions that will be wrapped individually. Once queued, the first bundle is dispatched to the network. - def processQueue(): Unit
Periodically deal with these concerns: the bundling and throttling of outgoing packets and the reordering of out-of-sequence incoming packets.
- val random: SecureRandom
- def randomBytes(amount: Int): ByteVector
A random series of bytes used as a challenge value.
A random series of bytes used as a challenge value.
- amount
the number of bytes
- returns
a random series of bytes
- def send(packet: PlanetSidePacket, sequence: Option[Int], crypto: Option[CryptoCoding]): ByteVector
- def send(packet: PlanetSideGamePacket): ByteVector
- def send(packet: PlanetSideCryptoPacket): ByteVector
- def send(packet: PlanetSideControlPacket): ByteVector
- def sendFirstBundle(): Unit
Take the first fully-prepared packet from the queue of prepared packets and send it to the client.
Take the first fully-prepared packet from the queue of prepared packets and send it to the client. Assign the dispatched packet the latest sequence number. Do not call unless confident the the queue has at least one element.
- Exceptions thrown
NoSuchElementExceptionif there is no packet to dequeue- See also
SlottedMetaPacket
- var serverMACBuffer: ByteVector
- def smp(slot: Int, data: ByteVector): SlottedMetaPacket
Create a new
SlottedMetaPacketwith the sequence number filled in and the packet added to the history.Create a new
SlottedMetaPacketwith the sequence number filled in and the packet added to the history.- slot
the slot for this packet, which influences the type of SMP
- data
hexadecimal data, the encoded packets to be placed in the SMP
- returns
the packet
- val smpHistoryLength: Int
- def splitPacket(packet: BitVector): Seq[PlanetSideControlPacket]
Split packet into multiple chunks (if necessary).
Split packet into multiple chunks (if necessary). Split packets are wrapped in a
HandleGamePacketand sent asSlottedMetaPacket4. The purpose ofSlottedMetaPacket4may or may not be to indicate a split packet. - def start(): Behavior[Command]
- var subslotMissingProcessor: Cancellable
Timer that handles the bundling and throttling of outgoing packets requesting packets with known subslot numbers
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- var timesInReorderQueue: Int
end of life stat
- var timesSubslotMissing: Int
end of life stat
- def toString(): String
- Definition Classes
- AnyRef → Any
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException]) @native()