<?php
/**
 *ESPacket.php
 * 用于网络二进制收发包
 */
class ESPacket {
	const SERVER_PACEKTVER = 1;
	const PACKET_BUFFER_SIZE = 150000;
	const PACKET_HEADER_SIZE = 15;

	private $m_packetBuffer;
	private $m_packetSize;
	private $m_CmdType;
	private $m_version;

	public function __construct(){
		$this->m_packetSize = 0;
		$this->m_packetBuffer = "";
		$this->m_version = self::SERVER_PACEKTVER;
		$this->m_CmdType = -1;
	}

	public function WriteBegin($CmdType, $version = self::SERVER_PACEKTVER){
		$this->m_CmdType = $CmdType;
		$this->m_version = $version;
	}

	public function WriteEnd(){
		//格式： 长度 + QE + version + extension + cmd + gameid + 验证码 + 数据
		$content  = pack("N", $this->m_packetSize + self::PACKET_HEADER_SIZE - 4);	//len
		$content .= "SA";									//QE
		$content .= pack("C", 1);							//version
		$content .= pack("C", 0);							//extension
		$content .= pack("N", $this->m_CmdType);			//cmd
		$content .= pack("n", 1);							//gameid
		$content .= pack("C", 1);							//验证码
		$content .= $this->m_packetBuffer;					//数据
		$this->m_packetBuffer	=	$content;
	}

	public function GetPacketBuffer(){
		return $this->m_packetBuffer;
	}

	public function GetPacketSize(){
		return $this->m_packetSize + self::PACKET_HEADER_SIZE;
	}

	public function WriteInt($value){
		$this->m_packetBuffer .= pack("N", $value);
		$this->m_packetSize += 4;
	}

	public function WriteInt64($value){
		// $high   = intval($value / (1<<32));
		// $low    = $value & ((1<<32)-1);
		// $this->m_packetBuffer .= pack("N", $high);
		// $this->m_packetBuffer .= pack("N", $low);
		// $this->m_packetSize += 8;

		$str = pack("N",$value>>32);
		$str .= pack("N",$value&0xffffffff);
		$this->m_packetBuffer .= $str;
		$this->m_packetSize	+= 8;

	}

	public function WriteByte($value){
		$this->m_packetBuffer .= pack("C", $value);
		$this->m_packetSize += 1;
	}

	public function WriteShort($value){
		$this->m_packetBuffer .= pack("n", $value);
		$this->m_packetSize += 2;
	}

	public function WriteString($value){
		$len = strlen($value)+1;
		$this->m_packetBuffer .= pack("N", $len);
		$this->m_packetBuffer .= $value;
		$this->m_packetBuffer .= pack("C", 0);
		$this->m_packetSize += $len+4;
	}

	public function ParsePacket(){
		if( $this->m_packetSize < self::PACKET_HEADER_SIZE ){
			return -1;
		}

		$header = substr($this->m_packetBuffer, 0, self::PACKET_HEADER_SIZE);
		$arr = unpack("NLen/c2Iden/cVer/cSubVer/NCmdType/nGameId/cCode", $header);
		if($arr['Iden1'] != ord('S') || $arr['Iden2'] != ord('A')){
			return -2;
		}
		$this->m_CmdType	=	$arr['CmdType'];
		if ($arr['Ver'] != $this->m_version ){
			return -3;
		}

		if($arr['Len'] >= 0 && $arr['Len'] > self::PACKET_BUFFER_SIZE - self::PACKET_HEADER_SIZE ){
			return -4;
		}
		$this->m_packetBuffer = substr($this->m_packetBuffer, self::PACKET_HEADER_SIZE);
		return 0;
	}

	public function SetRecvPacketBuffer($packet_buff, $packet_size){
		$this->m_packetBuffer = $packet_buff;
		$this->m_packetSize  = $packet_size;
	}

	public function ReadInt(){
		$temp = substr($this->m_packetBuffer, 0, 4);
		$value = unpack("N", $temp);
		$this->m_packetBuffer = substr($this->m_packetBuffer, 4);
		return $value[1];
	}

	public function ReadInt64(){
		$high = self::ReadInt();
		$low = self::ReadInt();
		return $high*(1<<32) + $low;
	}

	public function ReadShort(){
		$temp = substr($this->m_packetBuffer, 0, 2);
		$value = unpack("n", $temp);
		$this->m_packetBuffer = substr($this->m_packetBuffer, 2);
		return $value[1];
	}

	public function ReadString(){
		$len = $this->ReadInt();
		$value = substr($this->m_packetBuffer, 0, $len-1);
		$this->m_packetBuffer = substr($this->m_packetBuffer, $len);
		return $value;
	}

	public function ReadByte(){
		$temp = substr($this->m_packetBuffer, 0, 1);
		$value = unpack("C", $temp);
		$this->m_packetBuffer = substr($this->m_packetBuffer, 1);
		return $value[1];
	}
	public function GetCmd(){
		return $this->m_CmdType;
	}
}
