protected function decodeMessage(Protobuf\MessageInterface $message, $data) { // Get message descriptor $descriptor = Protobuf\Protobuf::getRegistry()->getDescriptor($message); $isLazy = $this->getOption('lazy'); $useTagNumber = $this->getOption('tags'); foreach ($data as $key => $v) { // Get the field by tag number or name $field = $useTagNumber ? $descriptor->getField($key) : $descriptor->getFieldByName($key); // Unknown field found if (!$field) { $unknown = new PhpArray\Unknown($key, gettype($v), $v); $message->addUnknown($unknown); continue; } if ($field->isRepeated()) { // Make sure the value is an array of values $v = is_array($v) && (empty($v) || is_int(key($v))) ? $v : array($v); // If we are packing lazy values use a LazyRepeat as container if ($isLazy && $field->getType() === Protobuf\Protobuf::TYPE_MESSAGE) { $v = new Protobuf\LazyRepeat($v); $v->codec = $this; $v->descriptor = $field; } else { foreach ($v as $k => $vv) { $v[$k] = $this->filterValue($vv, $field); } } } else { $v = $this->filterValue($v, $field); } $message->initValue($field->getName(), $v); } return $message; }
protected function decodeMessage(Protobuf\Message $message, $data) { // Get message descriptor $descriptor = Protobuf\Protobuf::getRegistry()->getDescriptor($message); // Split the index in UTF8 characters preg_match_all('/./u', $data[0], $chars); $chars = $chars[0]; for ($i = 1; $i < count($data); $i++) { $k = $this->c2i($chars[$i - 1]) - 48; $v = $data[$i]; $field = $descriptor->getField($k); if (NULL === $field) { // Unknown $unknown = new PhpArray\Unknown($k, gettype($v), $v); $message->addUnknown($unknown); continue; } $name = $field->getName(); if ($field->getType() === Protobuf\Protobuf::TYPE_MESSAGE) { $nested = $field->getReference(); if ($field->isRepeated()) { foreach ($v as $kk => $vv) { $v[$kk] = $this->decodeMessage(new $nested(), $vv); } $message->initValue($name, $v); } else { $obj = $this->decodeMessage(new $nested(), $v); $message->initValue($name, $obj); } } else { $message->initValue($name, $v); } } return $message; }
public function testSendMessage() { $message = new RpbPutReq(); $reqCode = RiakMessageCodes::PUT_REQ; $respCode = RiakMessageCodes::PUT_RESP; $respBody = Protobuf::encode(new RpbPutResp()); $stream = $this->getMock('Riak\\Client\\Core\\Transport\\Proto\\ProtoStream', [], [], '', false); $this->connection->expects($this->once())->method('send')->willReturn($stream); $this->connection->expects($this->once())->method('receive')->willReturn([$respCode, $respBody])->with($this->equalTo($stream)); $this->assertInstanceOf('Riak\\Client\\ProtoBuf\\RpbPutResp', $this->instance->send($message, $reqCode, $respCode)); }
protected function encodeMessage(Protobuf\MessageInterface $message, $level = 0) { $descriptor = Protobuf\Protobuf::getRegistry()->getDescriptor($message); $strict = $this->getOption('strict'); $indent = str_repeat(' ', $level); $data = ''; foreach ($descriptor->getFields() as $tag => $field) { $empty = !isset($message[$tag]); if ($strict && $empty && $field->isRequired() && !$field->hasDefault()) { throw new \UnexpectedValueException('Message ' . $descriptor->getName() . '\'s field tag ' . $tag . '(' . $field->getName() . ') is required but has no value'); } // skip not set values if ($empty) { continue; } $value = $message[$tag]; // don't send nulls or defaults over the wire if (NULL === $value || $field->hasDefault() && $field->getDefault() === $value) { continue; } $name = $field->getName(); if ($field->isRepeated()) { foreach ($value as $val) { // Skip nullified repeated values if (NULL === $val) { continue; } else { if ($field->getType() !== Protobuf\Protobuf::TYPE_MESSAGE) { $data .= $indent . $name . ': ' . json_encode($val) . "\n"; } else { $data .= $indent . $name . " {\n"; $data .= $this->encodeMessage($val, $level + 1); $data .= $indent . "}\n"; } } } } else { if ($field->getType() === Protobuf\Protobuf::TYPE_MESSAGE) { $data .= $indent . $name . " {\n"; $data .= $this->encodeMessage($value, $level + 1); $data .= $indent . "}\n"; } else { $data .= $indent . $name . ': ' . json_encode($value) . "\n"; } } } return $data; }
/** * @param \DrSlump\Protobuf\MessageInterface $message * @param string $data * @return \DrSlump\Protobuf\MessageInterface */ protected function _decodeMessage(\DrSlump\Protobuf\MessageInterface $message, $data) { $descriptor = Protobuf\Protobuf::getRegistry()->getDescriptor($message); $name = $descriptor->getName(); $res = $this->_describe($descriptor); $ret = \protobuf_decode($res, $data); // In non lazy mode we just pass the returned array thru the PhpArray codec if (!$this->getOption('lazy')) { if (!$this->_codec) { $this->_codec = new PhpArray(); $this->_codec->setOption('lazy', false); } return $this->_codec->decode($message, $ret); } // In lazy mode we need to walk thru the fields to convert message strings // to LazyValue / LazyRepeat foreach ($descriptor->getFields() as $field) { $name = $field->getName(); if (!isset($ret[$name])) { continue; } $value = $ret[$name]; if ($field->getType() === Protobuf\Protobuf::TYPE_MESSAGE) { if ($field->getRule() === Protobuf\Protobuf::RULE_REPEATED) { $value = new Protobuf\LazyRepeat($value); $value->codec = $this; $value->descriptor = $field; } else { $lazy = new Protobuf\LazyValue(); $lazy->codec = $this; $lazy->descriptor = $field; $lazy->value = $value; $value = $lazy; } } $message->initValue($name, $value); } return $message; }
protected function encodeMessage(Protobuf\Message $message) { $writer = new NativeWriter(); // Get message descriptor $descriptor = Protobuf\Protobuf::getRegistry()->getDescriptor($message); $strict = $this->getOption('strict'); foreach ($descriptor->getFields() as $tag => $field) { $empty = !isset($message[$tag]); if ($strict && $empty && $field->isRequired() && !$field->hasDefault()) { throw new \UnexpectedValueException('Message ' . get_class($message) . '\'s field tag ' . $tag . '(' . $field->getName() . ') is required but has no value'); } // skip not set values if ($empty) { continue; } $value = $message[$tag]; // don't send nulls or defaults over the wire if (NULL === $value || $field->hasDefault() && $field->getDefault() === $value) { continue; } $type = $field->getType(); $wire = $field->isPacked() ? self::WIRE_LENGTH : $this->getWireType($type, null); // Compute key with tag number and wire type $key = $tag << 3 | $wire; if ($field->isRepeated()) { // Packed fields are encoded as a length-delimited stream containing // the concatenated encoding of each value. if ($field->isPacked() && !empty($value)) { $subwriter = new NativeWriter(); foreach ($value as $val) { $this->encodeSimpleType($subwriter, $type, $val); } $data = $subwriter->getBytes(); $writer->varint($key); $writer->varint(mb_strlen($data, '8bit')); $writer->write($data); } else { foreach ($value as $val) { // Skip nullified repeated values if (NULL === $val) { continue; } else { if ($type !== Protobuf\Protobuf::TYPE_MESSAGE) { $writer->varint($key); $this->encodeSimpleType($writer, $type, $val); } else { $writer->varint($key); $data = $this->encodeMessage($val); $writer->varint(mb_strlen($data, '8bit')); $writer->write($data); } } } } } else { if ($type !== Protobuf\Protobuf::TYPE_MESSAGE) { $writer->varint($key); $this->encodeSimpleType($writer, $type, $value); } else { $writer->varint($key); $data = $this->encodeMessage($value); $writer->varint(mb_strlen($data, '8bit')); $writer->write($data); } } } return $writer->getBytes(); }
function testMultiCodecMessageWithRepeatedFields() { $jsonCodec = new Codec\Json(); $repeated = Protobuf\Protobuf::decode(Repeated::class, $this->bin_repeated_nested); $json = $jsonCodec->encode($repeated); $repeated = $jsonCodec->decode(new Repeated(), $json); $bin = Protobuf\Protobuf::encode($repeated); $this->assertEquals($bin, $this->bin_repeated_nested); }
/** * @param \DrSlump\Protobuf\Message $message * @param integer $code * * @return string */ private function encodeMessage(Message $message, $code) { return $this->connection->encode(Protobuf::encode($message), $code); }
require dirname(__FILE__) . '/../conf/db.php'; require dirname(__FILE__) . '/../vendor/autoload.php'; require dirname(__FILE__) . '/../proto/ping.php'; require dirname(__FILE__) . '/../proto/pong.php'; $receive_len = 30; $udp_socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); socket_bind($udp_socket, '0.0.0.0', 42001); $query_server_log = $db->prepare("\nSELECT\n server_log.server_id,\n server_log.nonce,\n server.session\nFROM\n server_log\nJOIN\n server\n ON\n server.id = server_log.server_id\nWHERE\n server_log.id = ?\nAND\n server_log.status = 'new'\n"); $query_update_server_log = $db->prepare("\nUPDATE\n server_log\nSET\n status = 'online',\n nonce = NULL,\n latency = 1000 * (NOW(6) - created),\n players = ?\nWHERE\n id = ?\n"); $query_update_server = $db->prepare("\nUPDATE\n server\nSET\n status = 'online',\n latency = (SELECT latency FROM server_log WHERE server_log.id = ?),\n players = ?,\n updated = NOW()\nWHERE\n id = ?\n"); print 'pongd started' . PHP_EOL; while (socket_recvfrom($udp_socket, $buf, $receive_len, 0, $ip, $port)) { print 'received ' . $receive_len . ' bytes from ' . $ip . PHP_EOL; if ('pong' === substr($buf, 0, 4)) { print 'looks like a pong' . PHP_EOL; $pong = \DrSlump\Protobuf\Protobuf::decode('Pong', substr($buf, 4)); $query_server_log->execute(array($pong->server_log_id)); if ($server_log = $query_server_log->fetch()) { print 'found server_log_id' . PHP_EOL; if ($pong->key === hash('sha1', $server_log->session . $server_log->nonce, true)) { print 'sha1 validated' . PHP_EOL; $query_update_server_log->execute(array($pong->player_count, $pong->server_log_id)); $query_update_server->execute(array($pong->server_log_id, $pong->player_count, $server_log->server_id)); print 'database updated' . PHP_EOL; } else { print 'invalid sha1!' . PHP_EOL; } } else { print 'invalid server_log_id!' . PHP_EOL; } }