Changeset View
Changeset View
Standalone View
Standalone View
src/channel/PhutilJSONProtocolChannel.php
| Show All 37 Lines | /* -( Protocol Implementation )-------------------------------------------- */ | ||||
| * ...where <len> is an 8-character, zero-padded integer written as a string. | * ...where <len> is an 8-character, zero-padded integer written as a string. | ||||
| * For example, this is a valid message: | * For example, this is a valid message: | ||||
| * | * | ||||
| * 00000015{"key":"value"} | * 00000015{"key":"value"} | ||||
| * | * | ||||
| * @task protocol | * @task protocol | ||||
| */ | */ | ||||
| protected function encodeMessage($message) { | protected function encodeMessage($message) { | ||||
| $message = json_encode($message); | if (!is_array($message)) { | ||||
| throw new Exception( | |||||
| pht( | |||||
| 'JSON protocol message must be an array, got some other '. | |||||
| 'type ("%s").', | |||||
| phutil_describe_type($message))); | |||||
| } | |||||
| $message = phutil_json_encode($message); | |||||
| $len = sprintf( | $len = sprintf( | ||||
| '%0'.self::SIZE_LENGTH.'.'.self::SIZE_LENGTH.'d', | '%0'.self::SIZE_LENGTH.'.'.self::SIZE_LENGTH.'d', | ||||
| strlen($message)); | strlen($message)); | ||||
| return "{$len}{$message}"; | return "{$len}{$message}"; | ||||
| } | } | ||||
| /** | /** | ||||
| * Decode a message received from the other end of the channel. Messages are | * Decode a message received from the other end of the channel. Messages are | ||||
| * decoded as associative arrays. | * decoded as associative arrays. | ||||
| * | * | ||||
| * @task protocol | * @task protocol | ||||
| */ | */ | ||||
| protected function decodeStream($data) { | protected function decodeStream($data) { | ||||
| $this->buf .= $data; | $this->buf .= $data; | ||||
| $objects = array(); | $objects = array(); | ||||
| while (strlen($this->buf) >= $this->byteLengthOfNextChunk) { | while (strlen($this->buf) >= $this->byteLengthOfNextChunk) { | ||||
| switch ($this->mode) { | switch ($this->mode) { | ||||
| case self::MODE_LENGTH: | case self::MODE_LENGTH: | ||||
| $len = substr($this->buf, 0, self::SIZE_LENGTH); | $len = substr($this->buf, 0, self::SIZE_LENGTH); | ||||
| $this->buf = substr($this->buf, self::SIZE_LENGTH); | $this->buf = substr($this->buf, self::SIZE_LENGTH); | ||||
| if (!preg_match('/^\d+\z/', $len)) { | |||||
| $full_buffer = $len.$this->buf; | |||||
| $full_length = strlen($full_buffer); | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Protocol channel expected %s-character, zero-padded '. | |||||
| 'numeric frame length, got something else ("%s"). Full '. | |||||
| 'buffer (of length %s) begins: %s', | |||||
| new PhutilNumber(self::SIZE_LENGTH), | |||||
| phutil_encode_log($len), | |||||
| new PhutilNumber($full_length), | |||||
| phutil_encode_log(substr($len.$this->buf, 0, 128)))); | |||||
| } | |||||
| $this->mode = self::MODE_OBJECT; | $this->mode = self::MODE_OBJECT; | ||||
| $this->byteLengthOfNextChunk = (int)$len; | $this->byteLengthOfNextChunk = (int)$len; | ||||
| break; | break; | ||||
| case self::MODE_OBJECT: | case self::MODE_OBJECT: | ||||
| $data = substr($this->buf, 0, $this->byteLengthOfNextChunk); | $data = substr($this->buf, 0, $this->byteLengthOfNextChunk); | ||||
| $this->buf = substr($this->buf, $this->byteLengthOfNextChunk); | $this->buf = substr($this->buf, $this->byteLengthOfNextChunk); | ||||
| try { | try { | ||||
| Show All 17 Lines | |||||