GenisysPro  for Minecraft PE/Windows 10 v1.1.x
Feature-rich server software for Minecraft PE and Windows 10 Edition
Session Class Reference

Public Member Functions

 __construct (SessionManager $sessionManager, $address, $port)
 
 getAddress ()
 
 getPort ()
 
 getID ()
 
 update ($time)
 
 disconnect ($reason="unknown")
 
 sendQueue ()
 
 addEncapsulatedToQueue (EncapsulatedPacket $packet, $flags=RakLib::PRIORITY_NORMAL)
 
 getState ()
 
 isTemporal ()
 
 handlePacket (Packet $packet)
 
 close ()
 

Data Fields

const STATE_UNCONNECTED = 0
 
const STATE_CONNECTING_1 = 1
 
const STATE_CONNECTING_2 = 2
 
const STATE_CONNECTED = 3
 
const MAX_SPLIT_SIZE = 128
 
const MAX_SPLIT_COUNT = 4
 

Static Public Attributes

static $WINDOW_SIZE = 2048
 

Constructor & Destructor Documentation

◆ __construct()

__construct ( SessionManager  $sessionManager,
  $address,
  $port 
)
100  {
101  $this->sessionManager = $sessionManager;
102  $this->address = $address;
103  $this->port = $port;
104  $this->sendQueue = new DATA_PACKET_4();
105  $this->lastUpdate = microtime(true);
106  $this->startTime = microtime(true);
107  $this->isActive = false;
108  $this->windowStart = -1;
109  $this->windowEnd = self::$WINDOW_SIZE;
110 
111  $this->reliableWindowStart = 0;
112  $this->reliableWindowEnd = self::$WINDOW_SIZE;
113 
114  for($i = 0; $i < 32; ++$i){
115  $this->channelIndex[$i] = 0;
116  }
117  }

Member Function Documentation

◆ addEncapsulatedToQueue()

addEncapsulatedToQueue ( EncapsulatedPacket  $packet,
  $flags = RakLib::PRIORITY_NORMAL 
)
Parameters
EncapsulatedPacket$packet
int$flags
262  {
263 
264  if(($packet->needACK = ($flags & RakLib::FLAG_NEED_ACK) > 0) === true){
265  $this->needACK[$packet->identifierACK] = [];
266  }
267 
268  if(
269  $packet->reliability === PacketReliability::RELIABLE or
270  $packet->reliability === PacketReliability::RELIABLE_ORDERED or
271  $packet->reliability === PacketReliability::RELIABLE_SEQUENCED or
272  $packet->reliability === PacketReliability::RELIABLE_WITH_ACK_RECEIPT or
274  ){
275  $packet->messageIndex = $this->messageIndex++;
276 
277  if($packet->reliability === PacketReliability::RELIABLE_ORDERED){
278  $packet->orderIndex = $this->channelIndex[$packet->orderChannel]++;
279  }
280  }
281 
282  if($packet->getTotalLength() + 4 > $this->mtuSize){
283  $buffers = str_split($packet->buffer, $this->mtuSize - 34);
284  $splitID = ++$this->splitID % 65536;
285  foreach($buffers as $count => $buffer){
286  $pk = new EncapsulatedPacket();
287  $pk->splitID = $splitID;
288  $pk->hasSplit = true;
289  $pk->splitCount = count($buffers);
290  $pk->reliability = $packet->reliability;
291  $pk->splitIndex = $count;
292  $pk->buffer = $buffer;
293  if($count > 0){
294  $pk->messageIndex = $this->messageIndex++;
295  }else{
296  $pk->messageIndex = $packet->messageIndex;
297  }
298  if($pk->reliability === PacketReliability::RELIABLE_ORDERED){
299  $pk->orderChannel = $packet->orderChannel;
300  $pk->orderIndex = $packet->orderIndex;
301  }
302  $this->addToQueue($pk, $flags | RakLib::PRIORITY_IMMEDIATE);
303  }
304  }else{
305  $this->addToQueue($packet, $flags);
306  }
307  }

◆ close()

close ( )
532  {
533  $data = "\x60\x00\x08\x00\x00\x00\x00\x00\x00\x00\x15";
534  $this->addEncapsulatedToQueue(EncapsulatedPacket::fromBinary($data)); //CLIENT_DISCONNECT packet 0x15
535  $this->sessionManager = null;
536  }

◆ disconnect()

disconnect (   $reason = "unknown")
202  {
203  $this->sessionManager->removeSession($this, $reason);
204  }

◆ getAddress()

getAddress ( )
119  {
120  return $this->address;
121  }

◆ getID()

getID ( )
127  {
128  return $this->id;
129  }

◆ getPort()

getPort ( )
123  {
124  return $this->port;
125  }

◆ getState()

getState ( )
373  {
374  return $this->state;
375  }

◆ handlePacket()

handlePacket ( Packet  $packet)
447  {
448  $this->isActive = true;
449  $this->lastUpdate = microtime(true);
450  if($this->state === self::STATE_CONNECTED or $this->state === self::STATE_CONNECTING_2){
451  if($packet::$ID >= 0x80 and $packet::$ID <= 0x8f and $packet instanceof DataPacket){ //Data packet
452  $packet->decode();
453 
454  if($packet->seqNumber < $this->windowStart or $packet->seqNumber > $this->windowEnd or isset($this->receivedWindow[$packet->seqNumber])){
455  return;
456  }
457 
458  $diff = $packet->seqNumber - $this->lastSeqNumber;
459 
460  unset($this->NACKQueue[$packet->seqNumber]);
461  $this->ACKQueue[$packet->seqNumber] = $packet->seqNumber;
462  $this->receivedWindow[$packet->seqNumber] = $packet->seqNumber;
463 
464  if($diff !== 1){
465  for($i = $this->lastSeqNumber + 1; $i < $packet->seqNumber; ++$i){
466  if(!isset($this->receivedWindow[$i])){
467  $this->NACKQueue[$i] = $i;
468  }
469  }
470  }
471 
472  if($diff >= 1){
473  $this->lastSeqNumber = $packet->seqNumber;
474  $this->windowStart += $diff;
475  $this->windowEnd += $diff;
476  }
477 
478  foreach($packet->packets as $pk){
479  $this->handleEncapsulatedPacket($pk);
480  }
481  }else{
482  if($packet instanceof ACK){
483  $packet->decode();
484  foreach($packet->packets as $seq){
485  if(isset($this->recoveryQueue[$seq])){
486  foreach($this->recoveryQueue[$seq]->packets as $pk){
487  if($pk instanceof EncapsulatedPacket and $pk->needACK and $pk->messageIndex !== null){
488  unset($this->needACK[$pk->identifierACK][$pk->messageIndex]);
489  }
490  }
491  unset($this->recoveryQueue[$seq]);
492  }
493  }
494  }elseif($packet instanceof NACK){
495  $packet->decode();
496  foreach($packet->packets as $seq){
497  if(isset($this->recoveryQueue[$seq])){
498  $pk = $this->recoveryQueue[$seq];
499  $pk->seqNumber = $this->sendSeqNumber++;
500  $this->packetToSend[] = $pk;
501  unset($this->recoveryQueue[$seq]);
502  }
503  }
504  }
505  }
506 
507  }elseif($packet::$ID > 0x00 and $packet::$ID < 0x80){ //Not Data packet :)
508  $packet->decode();
509  if($packet instanceof OPEN_CONNECTION_REQUEST_1){
510  $packet->protocol; //TODO: check protocol number and refuse connections
511  $pk = new OPEN_CONNECTION_REPLY_1();
512  $pk->mtuSize = $packet->mtuSize;
513  $pk->serverID = $this->sessionManager->getID();
514  $this->sendPacket($pk);
515  $this->state = self::STATE_CONNECTING_1;
516  }elseif($this->state === self::STATE_CONNECTING_1 and $packet instanceof OPEN_CONNECTION_REQUEST_2){
517  $this->id = $packet->clientID;
518  if($packet->serverPort === $this->sessionManager->getPort() or !$this->sessionManager->portChecking){
519  $this->mtuSize = min(abs($packet->mtuSize), 1464); //Max size, do not allow creating large buffers to fill server memory
520  $pk = new OPEN_CONNECTION_REPLY_2();
521  $pk->mtuSize = $this->mtuSize;
522  $pk->serverID = $this->sessionManager->getID();
523  $pk->clientAddress = $this->address;
524  $pk->clientPort = $this->port;
525  $this->sendPacket($pk);
526  $this->state = self::STATE_CONNECTING_2;
527  }
528  }
529  }
530  }

◆ isTemporal()

isTemporal ( )
377  {
378  return $this->isTemporal;
379  }

◆ sendQueue()

sendQueue ( )
210  {
211  if(count($this->sendQueue->packets) > 0){
212  $this->sendQueue->seqNumber = $this->sendSeqNumber++;
213  $this->sendPacket($this->sendQueue);
214  $this->sendQueue->sendTime = microtime(true);
215  $this->recoveryQueue[$this->sendQueue->seqNumber] = $this->sendQueue;
216  $this->sendQueue = new DATA_PACKET_4();
217  }
218  }

◆ update()

update (   $time)
131  {
132  if(!$this->isActive and ($this->lastUpdate + 10) < $time){
133  $this->disconnect("timeout");
134 
135  return;
136  }
137  $this->isActive = false;
138 
139  if(count($this->ACKQueue) > 0){
140  $pk = new ACK();
141  $pk->packets = $this->ACKQueue;
142  $this->sendPacket($pk);
143  $this->ACKQueue = [];
144  }
145 
146  if(count($this->NACKQueue) > 0){
147  $pk = new NACK();
148  $pk->packets = $this->NACKQueue;
149  $this->sendPacket($pk);
150  $this->NACKQueue = [];
151  }
152 
153  if(count($this->packetToSend) > 0){
154  $limit = 16;
155  foreach($this->packetToSend as $k => $pk){
156  $pk->sendTime = $time;
157  $pk->encode();
158  $this->recoveryQueue[$pk->seqNumber] = $pk;
159  unset($this->packetToSend[$k]);
160  $this->sendPacket($pk);
161 
162  if(--$limit <= 0){
163  break;
164  }
165  }
166 
167  if(count($this->packetToSend) > self::$WINDOW_SIZE){
168  $this->packetToSend = [];
169  }
170  }
171 
172  if(count($this->needACK) > 0){
173  foreach($this->needACK as $identifierACK => $indexes){
174  if(count($indexes) === 0){
175  unset($this->needACK[$identifierACK]);
176  $this->sessionManager->notifyACK($this, $identifierACK);
177  }
178  }
179  }
180 
181 
182  foreach($this->recoveryQueue as $seq => $pk){
183  if($pk->sendTime < (time() - 8)){
184  $this->packetToSend[] = $pk;
185  unset($this->recoveryQueue[$seq]);
186  }else{
187  break;
188  }
189  }
190 
191  foreach($this->receivedWindow as $seq => $bool){
192  if($seq < $this->windowStart){
193  unset($this->receivedWindow[$seq]);
194  }else{
195  break;
196  }
197  }
198 
199  $this->sendQueue();
200  }

Field Documentation

◆ $WINDOW_SIZE

$WINDOW_SIZE = 2048
static

◆ MAX_SPLIT_COUNT

const MAX_SPLIT_COUNT = 4

◆ MAX_SPLIT_SIZE

const MAX_SPLIT_SIZE = 128

◆ STATE_CONNECTED

const STATE_CONNECTED = 3

◆ STATE_CONNECTING_1

const STATE_CONNECTING_1 = 1

◆ STATE_CONNECTING_2

const STATE_CONNECTING_2 = 2

◆ STATE_UNCONNECTED

const STATE_UNCONNECTED = 0

The documentation for this class was generated from the following file: