Browse Source

Update addressbook example

- Implement streaming support on server side
- Rework qtprotobuf example client to demonstrate async update
Alexey Edelev 5 years ago
parent
commit
050361d086

+ 4 - 5
examples/addressbook/addressbookengine.cpp

@@ -37,16 +37,15 @@ AddressBookEngine::AddressBookEngine() : QObject()
 {
     std::shared_ptr<qtprotobuf::AbstractChannel> channel(new qtprotobuf::Http2Channel("localhost", 65001));
     m_client->attachChannel(channel);
-    m_client->getContacts(ListFrame(), this, [this](qtprotobuf::AsyncReply *reply) {
-        m_contacts->reset(reply->read<Contacts>().list());
+    m_client->subscribeContactsUpdates(ListFrame());
+    connect(m_client, &AddressBookClient::contactsUpdated, this, [this](const Contacts &contacts) {
+        m_contacts->reset(contacts.list());
     });
 }
 
 void AddressBookEngine::addContact(qtprotobuf::examples::Contact *contact)
 {
-    m_client->addContact(*contact, this, [this](qtprotobuf::AsyncReply *reply) {
-        m_contacts->reset(reply->read<Contacts>().list());
-    });
+    m_client->addContact(*contact);
 }
 
 AddressBookEngine::~AddressBookEngine()

+ 1 - 1
examples/addressbook/proto/addressbook.proto

@@ -77,7 +77,7 @@ message ListFrame {
 service AddressBook {
     rpc addContact(Contact) returns (Contacts) {}
     rpc removeContact(Contact) returns (Contacts) {}
-    rpc getContacts(ListFrame) returns (Contacts) {}
+    rpc contacts(ListFrame) returns (stream Contacts) {}
     rpc makeCall(Contact) returns (SimpleResult) {}
     rpc navigateTo(Address) returns (SimpleResult) {}
 }

+ 13 - 13
examples/addressbookserver/addressbook.grpc.pb.cc

@@ -19,7 +19,7 @@ namespace examples {
 static const char* AddressBook_method_names[] = {
   "/qtprotobuf.examples.AddressBook/addContact",
   "/qtprotobuf.examples.AddressBook/removeContact",
-  "/qtprotobuf.examples.AddressBook/getContacts",
+  "/qtprotobuf.examples.AddressBook/contacts",
   "/qtprotobuf.examples.AddressBook/makeCall",
   "/qtprotobuf.examples.AddressBook/navigateTo",
 };
@@ -33,7 +33,7 @@ std::unique_ptr< AddressBook::Stub> AddressBook::NewStub(const std::shared_ptr<
 AddressBook::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel)
   : channel_(channel), rpcmethod_addContact_(AddressBook_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
   , rpcmethod_removeContact_(AddressBook_method_names[1], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
-  , rpcmethod_getContacts_(AddressBook_method_names[2], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  , rpcmethod_contacts_(AddressBook_method_names[2], ::grpc::internal::RpcMethod::SERVER_STREAMING, channel)
   , rpcmethod_makeCall_(AddressBook_method_names[3], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
   , rpcmethod_navigateTo_(AddressBook_method_names[4], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
   {}
@@ -62,16 +62,16 @@ AddressBook::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channe
   return ::grpc::internal::ClientAsyncResponseReaderFactory< ::qtprotobuf::examples::Contacts>::Create(channel_.get(), cq, rpcmethod_removeContact_, context, request, false);
 }
 
-::grpc::Status AddressBook::Stub::getContacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::qtprotobuf::examples::Contacts* response) {
-  return ::grpc::internal::BlockingUnaryCall(channel_.get(), rpcmethod_getContacts_, context, request, response);
+::grpc::ClientReader< ::qtprotobuf::examples::Contacts>* AddressBook::Stub::contactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request) {
+  return ::grpc::internal::ClientReaderFactory< ::qtprotobuf::examples::Contacts>::Create(channel_.get(), rpcmethod_contacts_, context, request);
 }
 
-::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>* AddressBook::Stub::AsyncgetContactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
-  return ::grpc::internal::ClientAsyncResponseReaderFactory< ::qtprotobuf::examples::Contacts>::Create(channel_.get(), cq, rpcmethod_getContacts_, context, request, true);
+::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>* AddressBook::Stub::AsynccontactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq, void* tag) {
+  return ::grpc::internal::ClientAsyncReaderFactory< ::qtprotobuf::examples::Contacts>::Create(channel_.get(), cq, rpcmethod_contacts_, context, request, true, tag);
 }
 
-::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>* AddressBook::Stub::PrepareAsyncgetContactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
-  return ::grpc::internal::ClientAsyncResponseReaderFactory< ::qtprotobuf::examples::Contacts>::Create(channel_.get(), cq, rpcmethod_getContacts_, context, request, false);
+::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>* AddressBook::Stub::PrepareAsynccontactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc::internal::ClientAsyncReaderFactory< ::qtprotobuf::examples::Contacts>::Create(channel_.get(), cq, rpcmethod_contacts_, context, request, false, nullptr);
 }
 
 ::grpc::Status AddressBook::Stub::makeCall(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::qtprotobuf::examples::SimpleResult* response) {
@@ -111,9 +111,9 @@ AddressBook::Service::Service() {
           std::mem_fn(&AddressBook::Service::removeContact), this)));
   AddMethod(new ::grpc::internal::RpcServiceMethod(
       AddressBook_method_names[2],
-      ::grpc::internal::RpcMethod::NORMAL_RPC,
-      new ::grpc::internal::RpcMethodHandler< AddressBook::Service, ::qtprotobuf::examples::ListFrame, ::qtprotobuf::examples::Contacts>(
-          std::mem_fn(&AddressBook::Service::getContacts), this)));
+      ::grpc::internal::RpcMethod::SERVER_STREAMING,
+      new ::grpc::internal::ServerStreamingHandler< AddressBook::Service, ::qtprotobuf::examples::ListFrame, ::qtprotobuf::examples::Contacts>(
+          std::mem_fn(&AddressBook::Service::contacts), this)));
   AddMethod(new ::grpc::internal::RpcServiceMethod(
       AddressBook_method_names[3],
       ::grpc::internal::RpcMethod::NORMAL_RPC,
@@ -143,10 +143,10 @@ AddressBook::Service::~Service() {
   return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
 }
 
-::grpc::Status AddressBook::Service::getContacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::qtprotobuf::examples::Contacts* response) {
+::grpc::Status AddressBook::Service::contacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerWriter< ::qtprotobuf::examples::Contacts>* writer) {
   (void) context;
   (void) request;
-  (void) response;
+  (void) writer;
   return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
 }
 

+ 62 - 56
examples/addressbookserver/addressbook.grpc.pb.h

@@ -74,12 +74,14 @@ class AddressBook final {
     std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>> PrepareAsyncremoveContact(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) {
       return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>>(PrepareAsyncremoveContactRaw(context, request, cq));
     }
-    virtual ::grpc::Status getContacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::qtprotobuf::examples::Contacts* response) = 0;
-    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>> AsyncgetContacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
-      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>>(AsyncgetContactsRaw(context, request, cq));
+    std::unique_ptr< ::grpc::ClientReaderInterface< ::qtprotobuf::examples::Contacts>> contacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request) {
+      return std::unique_ptr< ::grpc::ClientReaderInterface< ::qtprotobuf::examples::Contacts>>(contactsRaw(context, request));
     }
-    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>> PrepareAsyncgetContacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
-      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>>(PrepareAsyncgetContactsRaw(context, request, cq));
+    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::qtprotobuf::examples::Contacts>> Asynccontacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq, void* tag) {
+      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::qtprotobuf::examples::Contacts>>(AsynccontactsRaw(context, request, cq, tag));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::qtprotobuf::examples::Contacts>> PrepareAsynccontacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::qtprotobuf::examples::Contacts>>(PrepareAsynccontactsRaw(context, request, cq));
     }
     virtual ::grpc::Status makeCall(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::qtprotobuf::examples::SimpleResult* response) = 0;
     std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::SimpleResult>> AsyncmakeCall(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) {
@@ -100,8 +102,9 @@ class AddressBook final {
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>* PrepareAsyncaddContactRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>* AsyncremoveContactRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>* PrepareAsyncremoveContactRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) = 0;
-    virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>* AsyncgetContactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) = 0;
-    virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::Contacts>* PrepareAsyncgetContactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientReaderInterface< ::qtprotobuf::examples::Contacts>* contactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request) = 0;
+    virtual ::grpc::ClientAsyncReaderInterface< ::qtprotobuf::examples::Contacts>* AsynccontactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
+    virtual ::grpc::ClientAsyncReaderInterface< ::qtprotobuf::examples::Contacts>* PrepareAsynccontactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::SimpleResult>* AsyncmakeCallRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::SimpleResult>* PrepareAsyncmakeCallRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::qtprotobuf::examples::SimpleResult>* AsyncnavigateToRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Address& request, ::grpc::CompletionQueue* cq) = 0;
@@ -124,12 +127,14 @@ class AddressBook final {
     std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>> PrepareAsyncremoveContact(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) {
       return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>>(PrepareAsyncremoveContactRaw(context, request, cq));
     }
-    ::grpc::Status getContacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::qtprotobuf::examples::Contacts* response) override;
-    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>> AsyncgetContacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
-      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>>(AsyncgetContactsRaw(context, request, cq));
+    std::unique_ptr< ::grpc::ClientReader< ::qtprotobuf::examples::Contacts>> contacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request) {
+      return std::unique_ptr< ::grpc::ClientReader< ::qtprotobuf::examples::Contacts>>(contactsRaw(context, request));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>> Asynccontacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq, void* tag) {
+      return std::unique_ptr< ::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>>(AsynccontactsRaw(context, request, cq, tag));
     }
-    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>> PrepareAsyncgetContacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
-      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>>(PrepareAsyncgetContactsRaw(context, request, cq));
+    std::unique_ptr< ::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>> PrepareAsynccontacts(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>>(PrepareAsynccontactsRaw(context, request, cq));
     }
     ::grpc::Status makeCall(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::qtprotobuf::examples::SimpleResult* response) override;
     std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::SimpleResult>> AsyncmakeCall(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) {
@@ -152,15 +157,16 @@ class AddressBook final {
     ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>* PrepareAsyncaddContactRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>* AsyncremoveContactRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>* PrepareAsyncremoveContactRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) override;
-    ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>* AsyncgetContactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) override;
-    ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::Contacts>* PrepareAsyncgetContactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientReader< ::qtprotobuf::examples::Contacts>* contactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request) override;
+    ::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>* AsynccontactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq, void* tag) override;
+    ::grpc::ClientAsyncReader< ::qtprotobuf::examples::Contacts>* PrepareAsynccontactsRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::ListFrame& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::SimpleResult>* AsyncmakeCallRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::SimpleResult>* PrepareAsyncmakeCallRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Contact& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::SimpleResult>* AsyncnavigateToRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Address& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::qtprotobuf::examples::SimpleResult>* PrepareAsyncnavigateToRaw(::grpc::ClientContext* context, const ::qtprotobuf::examples::Address& request, ::grpc::CompletionQueue* cq) override;
     const ::grpc::internal::RpcMethod rpcmethod_addContact_;
     const ::grpc::internal::RpcMethod rpcmethod_removeContact_;
-    const ::grpc::internal::RpcMethod rpcmethod_getContacts_;
+    const ::grpc::internal::RpcMethod rpcmethod_contacts_;
     const ::grpc::internal::RpcMethod rpcmethod_makeCall_;
     const ::grpc::internal::RpcMethod rpcmethod_navigateTo_;
   };
@@ -172,7 +178,7 @@ class AddressBook final {
     virtual ~Service();
     virtual ::grpc::Status addContact(::grpc::ServerContext* context, const ::qtprotobuf::examples::Contact* request, ::qtprotobuf::examples::Contacts* response);
     virtual ::grpc::Status removeContact(::grpc::ServerContext* context, const ::qtprotobuf::examples::Contact* request, ::qtprotobuf::examples::Contacts* response);
-    virtual ::grpc::Status getContacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::qtprotobuf::examples::Contacts* response);
+    virtual ::grpc::Status contacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerWriter< ::qtprotobuf::examples::Contacts>* writer);
     virtual ::grpc::Status makeCall(::grpc::ServerContext* context, const ::qtprotobuf::examples::Contact* request, ::qtprotobuf::examples::SimpleResult* response);
     virtual ::grpc::Status navigateTo(::grpc::ServerContext* context, const ::qtprotobuf::examples::Address* request, ::qtprotobuf::examples::SimpleResult* response);
   };
@@ -217,23 +223,23 @@ class AddressBook final {
     }
   };
   template <class BaseClass>
-  class WithAsyncMethod_getContacts : public BaseClass {
+  class WithAsyncMethod_contacts : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service *service) {}
    public:
-    WithAsyncMethod_getContacts() {
+    WithAsyncMethod_contacts() {
       ::grpc::Service::MarkMethodAsync(2);
     }
-    ~WithAsyncMethod_getContacts() override {
+    ~WithAsyncMethod_contacts() override {
       BaseClassMustBeDerivedFromService(this);
     }
     // disable synchronous version of this method
-    ::grpc::Status getContacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::qtprotobuf::examples::Contacts* response) override {
+    ::grpc::Status contacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerWriter< ::qtprotobuf::examples::Contacts>* writer) override {
       abort();
       return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
     }
-    void RequestgetContacts(::grpc::ServerContext* context, ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerAsyncResponseWriter< ::qtprotobuf::examples::Contacts>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
-      ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag);
+    void Requestcontacts(::grpc::ServerContext* context, ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerAsyncWriter< ::qtprotobuf::examples::Contacts>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncServerStreaming(2, context, request, writer, new_call_cq, notification_cq, tag);
     }
   };
   template <class BaseClass>
@@ -276,7 +282,7 @@ class AddressBook final {
       ::grpc::Service::RequestAsyncUnary(4, context, request, response, new_call_cq, notification_cq, tag);
     }
   };
-  typedef WithAsyncMethod_addContact<WithAsyncMethod_removeContact<WithAsyncMethod_getContacts<WithAsyncMethod_makeCall<WithAsyncMethod_navigateTo<Service > > > > > AsyncService;
+  typedef WithAsyncMethod_addContact<WithAsyncMethod_removeContact<WithAsyncMethod_contacts<WithAsyncMethod_makeCall<WithAsyncMethod_navigateTo<Service > > > > > AsyncService;
   template <class BaseClass>
   class WithGenericMethod_addContact : public BaseClass {
    private:
@@ -312,18 +318,18 @@ class AddressBook final {
     }
   };
   template <class BaseClass>
-  class WithGenericMethod_getContacts : public BaseClass {
+  class WithGenericMethod_contacts : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service *service) {}
    public:
-    WithGenericMethod_getContacts() {
+    WithGenericMethod_contacts() {
       ::grpc::Service::MarkMethodGeneric(2);
     }
-    ~WithGenericMethod_getContacts() override {
+    ~WithGenericMethod_contacts() override {
       BaseClassMustBeDerivedFromService(this);
     }
     // disable synchronous version of this method
-    ::grpc::Status getContacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::qtprotobuf::examples::Contacts* response) override {
+    ::grpc::Status contacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerWriter< ::qtprotobuf::examples::Contacts>* writer) override {
       abort();
       return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
     }
@@ -403,23 +409,23 @@ class AddressBook final {
     }
   };
   template <class BaseClass>
-  class WithRawMethod_getContacts : public BaseClass {
+  class WithRawMethod_contacts : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service *service) {}
    public:
-    WithRawMethod_getContacts() {
+    WithRawMethod_contacts() {
       ::grpc::Service::MarkMethodRaw(2);
     }
-    ~WithRawMethod_getContacts() override {
+    ~WithRawMethod_contacts() override {
       BaseClassMustBeDerivedFromService(this);
     }
     // disable synchronous version of this method
-    ::grpc::Status getContacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::qtprotobuf::examples::Contacts* response) override {
+    ::grpc::Status contacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerWriter< ::qtprotobuf::examples::Contacts>* writer) override {
       abort();
       return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
     }
-    void RequestgetContacts(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
-      ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag);
+    void Requestcontacts(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncWriter< ::grpc::ByteBuffer>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncServerStreaming(2, context, request, writer, new_call_cq, notification_cq, tag);
     }
   };
   template <class BaseClass>
@@ -503,26 +509,6 @@ class AddressBook final {
     virtual ::grpc::Status StreamedremoveContact(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::qtprotobuf::examples::Contact,::qtprotobuf::examples::Contacts>* server_unary_streamer) = 0;
   };
   template <class BaseClass>
-  class WithStreamedUnaryMethod_getContacts : public BaseClass {
-   private:
-    void BaseClassMustBeDerivedFromService(const Service *service) {}
-   public:
-    WithStreamedUnaryMethod_getContacts() {
-      ::grpc::Service::MarkMethodStreamed(2,
-        new ::grpc::internal::StreamedUnaryHandler< ::qtprotobuf::examples::ListFrame, ::qtprotobuf::examples::Contacts>(std::bind(&WithStreamedUnaryMethod_getContacts<BaseClass>::StreamedgetContacts, this, std::placeholders::_1, std::placeholders::_2)));
-    }
-    ~WithStreamedUnaryMethod_getContacts() override {
-      BaseClassMustBeDerivedFromService(this);
-    }
-    // disable regular version of this method
-    ::grpc::Status getContacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::qtprotobuf::examples::Contacts* response) override {
-      abort();
-      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
-    }
-    // replace default version of method with streamed unary
-    virtual ::grpc::Status StreamedgetContacts(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::qtprotobuf::examples::ListFrame,::qtprotobuf::examples::Contacts>* server_unary_streamer) = 0;
-  };
-  template <class BaseClass>
   class WithStreamedUnaryMethod_makeCall : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service *service) {}
@@ -562,9 +548,29 @@ class AddressBook final {
     // replace default version of method with streamed unary
     virtual ::grpc::Status StreamednavigateTo(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::qtprotobuf::examples::Address,::qtprotobuf::examples::SimpleResult>* server_unary_streamer) = 0;
   };
-  typedef WithStreamedUnaryMethod_addContact<WithStreamedUnaryMethod_removeContact<WithStreamedUnaryMethod_getContacts<WithStreamedUnaryMethod_makeCall<WithStreamedUnaryMethod_navigateTo<Service > > > > > StreamedUnaryService;
-  typedef Service SplitStreamedService;
-  typedef WithStreamedUnaryMethod_addContact<WithStreamedUnaryMethod_removeContact<WithStreamedUnaryMethod_getContacts<WithStreamedUnaryMethod_makeCall<WithStreamedUnaryMethod_navigateTo<Service > > > > > StreamedService;
+  typedef WithStreamedUnaryMethod_addContact<WithStreamedUnaryMethod_removeContact<WithStreamedUnaryMethod_makeCall<WithStreamedUnaryMethod_navigateTo<Service > > > > StreamedUnaryService;
+  template <class BaseClass>
+  class WithSplitStreamingMethod_contacts : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service *service) {}
+   public:
+    WithSplitStreamingMethod_contacts() {
+      ::grpc::Service::MarkMethodStreamed(2,
+        new ::grpc::internal::SplitServerStreamingHandler< ::qtprotobuf::examples::ListFrame, ::qtprotobuf::examples::Contacts>(std::bind(&WithSplitStreamingMethod_contacts<BaseClass>::Streamedcontacts, this, std::placeholders::_1, std::placeholders::_2)));
+    }
+    ~WithSplitStreamingMethod_contacts() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status contacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::grpc::ServerWriter< ::qtprotobuf::examples::Contacts>* writer) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with split streamed
+    virtual ::grpc::Status Streamedcontacts(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::qtprotobuf::examples::ListFrame,::qtprotobuf::examples::Contacts>* server_split_streamer) = 0;
+  };
+  typedef WithSplitStreamingMethod_contacts<Service > SplitStreamedService;
+  typedef WithStreamedUnaryMethod_addContact<WithStreamedUnaryMethod_removeContact<WithSplitStreamingMethod_contacts<WithStreamedUnaryMethod_makeCall<WithStreamedUnaryMethod_navigateTo<Service > > > > > StreamedService;
 };
 
 }  // namespace examples

+ 55 - 184
examples/addressbookserver/addressbook.pb.cc

@@ -22,7 +22,6 @@
 namespace protobuf_addressbook_2eproto {
 extern PROTOBUF_INTERNAL_EXPORT_protobuf_addressbook_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Address;
 extern PROTOBUF_INTERNAL_EXPORT_protobuf_addressbook_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_PhoneNumber;
-extern PROTOBUF_INTERNAL_EXPORT_protobuf_addressbook_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_Contact_PhonesEntry_DoNotUse;
 extern PROTOBUF_INTERNAL_EXPORT_protobuf_addressbook_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_Job;
 extern PROTOBUF_INTERNAL_EXPORT_protobuf_addressbook_2eproto ::google::protobuf::internal::SCCInfo<3> scc_info_Contact;
 }  // namespace protobuf_addressbook_2eproto
@@ -43,11 +42,6 @@ class JobDefaultTypeInternal {
   ::google::protobuf::internal::ExplicitlyConstructed<Job>
       _instance;
 } _Job_default_instance_;
-class Contact_PhonesEntry_DoNotUseDefaultTypeInternal {
- public:
-  ::google::protobuf::internal::ExplicitlyConstructed<Contact_PhonesEntry_DoNotUse>
-      _instance;
-} _Contact_PhonesEntry_DoNotUse_default_instance_;
 class ContactDefaultTypeInternal {
  public:
   ::google::protobuf::internal::ExplicitlyConstructed<Contact>
@@ -114,20 +108,6 @@ static void InitDefaultsJob() {
     {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsJob}, {
       &protobuf_addressbook_2eproto::scc_info_Address.base,}};
 
-static void InitDefaultsContact_PhonesEntry_DoNotUse() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &::qtprotobuf::examples::_Contact_PhonesEntry_DoNotUse_default_instance_;
-    new (ptr) ::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse();
-  }
-  ::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse::InitAsDefaultInstance();
-}
-
-::google::protobuf::internal::SCCInfo<1> scc_info_Contact_PhonesEntry_DoNotUse =
-    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsContact_PhonesEntry_DoNotUse}, {
-      &protobuf_addressbook_2eproto::scc_info_PhoneNumber.base,}};
-
 static void InitDefaultsContact() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
@@ -141,7 +121,7 @@ static void InitDefaultsContact() {
 
 ::google::protobuf::internal::SCCInfo<3> scc_info_Contact =
     {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 3, InitDefaultsContact}, {
-      &protobuf_addressbook_2eproto::scc_info_Contact_PhonesEntry_DoNotUse.base,
+      &protobuf_addressbook_2eproto::scc_info_PhoneNumber.base,
       &protobuf_addressbook_2eproto::scc_info_Address.base,
       &protobuf_addressbook_2eproto::scc_info_Job.base,}};
 
@@ -192,14 +172,13 @@ void InitDefaults() {
   ::google::protobuf::internal::InitSCC(&scc_info_PhoneNumber.base);
   ::google::protobuf::internal::InitSCC(&scc_info_Address.base);
   ::google::protobuf::internal::InitSCC(&scc_info_Job.base);
-  ::google::protobuf::internal::InitSCC(&scc_info_Contact_PhonesEntry_DoNotUse.base);
   ::google::protobuf::internal::InitSCC(&scc_info_Contact.base);
   ::google::protobuf::internal::InitSCC(&scc_info_Contacts.base);
   ::google::protobuf::internal::InitSCC(&scc_info_SimpleResult.base);
   ::google::protobuf::internal::InitSCC(&scc_info_ListFrame.base);
 }
 
-::google::protobuf::Metadata file_level_metadata[8];
+::google::protobuf::Metadata file_level_metadata[7];
 const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors[1];
 
 const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
@@ -227,15 +206,6 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUT
   ~0u,  // no _weak_field_map_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::qtprotobuf::examples::Job, title_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::qtprotobuf::examples::Job, officeaddress_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse, _has_bits_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse, key_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse, value_),
-  0,
-  1,
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::qtprotobuf::examples::Contact, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -271,18 +241,16 @@ static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROT
   { 0, -1, sizeof(::qtprotobuf::examples::PhoneNumber)},
   { 7, -1, sizeof(::qtprotobuf::examples::Address)},
   { 17, -1, sizeof(::qtprotobuf::examples::Job)},
-  { 24, 31, sizeof(::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse)},
-  { 33, -1, sizeof(::qtprotobuf::examples::Contact)},
-  { 44, -1, sizeof(::qtprotobuf::examples::Contacts)},
-  { 50, -1, sizeof(::qtprotobuf::examples::SimpleResult)},
-  { 56, -1, sizeof(::qtprotobuf::examples::ListFrame)},
+  { 24, -1, sizeof(::qtprotobuf::examples::Contact)},
+  { 35, -1, sizeof(::qtprotobuf::examples::Contacts)},
+  { 41, -1, sizeof(::qtprotobuf::examples::SimpleResult)},
+  { 47, -1, sizeof(::qtprotobuf::examples::ListFrame)},
 };
 
 static ::google::protobuf::Message const * const file_default_instances[] = {
   reinterpret_cast<const ::google::protobuf::Message*>(&::qtprotobuf::examples::_PhoneNumber_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&::qtprotobuf::examples::_Address_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&::qtprotobuf::examples::_Job_default_instance_),
-  reinterpret_cast<const ::google::protobuf::Message*>(&::qtprotobuf::examples::_Contact_PhonesEntry_DoNotUse_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&::qtprotobuf::examples::_Contact_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&::qtprotobuf::examples::_Contacts_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&::qtprotobuf::examples::_SimpleResult_default_instance_),
@@ -304,7 +272,7 @@ void protobuf_AssignDescriptorsOnce() {
 void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
 void protobuf_RegisterTypes(const ::std::string&) {
   protobuf_AssignDescriptorsOnce();
-  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 8);
+  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 7);
 }
 
 void AddDescriptorsImpl() {
@@ -316,33 +284,31 @@ void AddDescriptorsImpl() {
       "\022\026\n\016streetAddress1\030\002 \001(\t\022\026\n\016streetAddres"
       "s2\030\003 \001(\t\022\r\n\005state\030\004 \001(\t\022\017\n\007country\030\005 \001(\r"
       "\"I\n\003Job\022\r\n\005title\030\001 \001(\t\0223\n\rofficeAddress\030"
-      "\002 \001(\0132\034.qtprotobuf.examples.Address\"\333\002\n\007"
+      "\002 \001(\0132\034.qtprotobuf.examples.Address\"\202\002\n\007"
       "Contact\022\021\n\tfirstName\030\001 \001(\t\022\020\n\010lastName\030\002"
-      " \001(\t\022\022\n\nmiddleName\030\003 \001(\t\0228\n\006phones\030\004 \003(\013"
-      "2(.qtprotobuf.examples.Contact.PhonesEnt"
-      "ry\022-\n\007address\030\005 \001(\0132\034.qtprotobuf.example"
-      "s.Address\022%\n\003job\030\006 \001(\0132\030.qtprotobuf.exam"
-      "ples.Job\032O\n\013PhonesEntry\022\013\n\003key\030\001 \001(\005\022/\n\005"
-      "value\030\002 \001(\0132 .qtprotobuf.examples.PhoneN"
-      "umber:\0028\001\"6\n\tPhoneType\022\010\n\004Home\020\000\022\010\n\004Work"
-      "\020\001\022\n\n\006Mobile\020\002\022\t\n\005Other\020\003\"6\n\010Contacts\022*\n"
-      "\004list\030\001 \003(\0132\034.qtprotobuf.examples.Contac"
-      "t\"\032\n\014SimpleResult\022\n\n\002ok\030\001 \001(\010\"\'\n\tListFra"
-      "me\022\r\n\005start\030\001 \001(\021\022\013\n\003end\030\002 \001(\0212\232\003\n\013Addre"
-      "ssBook\022K\n\naddContact\022\034.qtprotobuf.exampl"
-      "es.Contact\032\035.qtprotobuf.examples.Contact"
-      "s\"\000\022N\n\rremoveContact\022\034.qtprotobuf.exampl"
-      "es.Contact\032\035.qtprotobuf.examples.Contact"
-      "s\"\000\022N\n\013getContacts\022\036.qtprotobuf.examples"
-      ".ListFrame\032\035.qtprotobuf.examples.Contact"
-      "s\"\000\022M\n\010makeCall\022\034.qtprotobuf.examples.Co"
-      "ntact\032!.qtprotobuf.examples.SimpleResult"
-      "\"\000\022O\n\nnavigateTo\022\034.qtprotobuf.examples.A"
-      "ddress\032!.qtprotobuf.examples.SimpleResul"
-      "t\"\000b\006proto3"
+      " \001(\t\022\022\n\nmiddleName\030\003 \001(\t\0220\n\006phones\030\004 \003(\013"
+      "2 .qtprotobuf.examples.PhoneNumber\022-\n\007ad"
+      "dress\030\005 \001(\0132\034.qtprotobuf.examples.Addres"
+      "s\022%\n\003job\030\006 \001(\0132\030.qtprotobuf.examples.Job"
+      "\"6\n\tPhoneType\022\010\n\004Home\020\000\022\010\n\004Work\020\001\022\n\n\006Mob"
+      "ile\020\002\022\t\n\005Other\020\003\"6\n\010Contacts\022*\n\004list\030\001 \003"
+      "(\0132\034.qtprotobuf.examples.Contact\"\032\n\014Simp"
+      "leResult\022\n\n\002ok\030\001 \001(\010\"\'\n\tListFrame\022\r\n\005sta"
+      "rt\030\001 \001(\021\022\013\n\003end\030\002 \001(\0212\231\003\n\013AddressBook\022K\n"
+      "\naddContact\022\034.qtprotobuf.examples.Contac"
+      "t\032\035.qtprotobuf.examples.Contacts\"\000\022N\n\rre"
+      "moveContact\022\034.qtprotobuf.examples.Contac"
+      "t\032\035.qtprotobuf.examples.Contacts\"\000\022M\n\010co"
+      "ntacts\022\036.qtprotobuf.examples.ListFrame\032\035"
+      ".qtprotobuf.examples.Contacts\"\0000\001\022M\n\010mak"
+      "eCall\022\034.qtprotobuf.examples.Contact\032!.qt"
+      "protobuf.examples.SimpleResult\"\000\022O\n\nnavi"
+      "gateTo\022\034.qtprotobuf.examples.Address\032!.q"
+      "tprotobuf.examples.SimpleResult\"\000b\006proto"
+      "3"
   };
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
-      descriptor, 1171);
+      descriptor, 1081);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "addressbook.proto", &protobuf_RegisterTypes);
 }
@@ -1382,23 +1348,6 @@ void Job::InternalSwap(Job* other) {
 }
 
 
-// ===================================================================
-
-Contact_PhonesEntry_DoNotUse::Contact_PhonesEntry_DoNotUse() {}
-Contact_PhonesEntry_DoNotUse::Contact_PhonesEntry_DoNotUse(::google::protobuf::Arena* arena) : SuperType(arena) {}
-void Contact_PhonesEntry_DoNotUse::MergeFrom(const Contact_PhonesEntry_DoNotUse& other) {
-  MergeFromInternal(other);
-}
-::google::protobuf::Metadata Contact_PhonesEntry_DoNotUse::GetMetadata() const {
-  ::protobuf_addressbook_2eproto::protobuf_AssignDescriptorsOnce();
-  return ::protobuf_addressbook_2eproto::file_level_metadata[3];
-}
-void Contact_PhonesEntry_DoNotUse::MergeFrom(
-    const ::google::protobuf::Message& other) {
-  ::google::protobuf::Message::MergeFrom(other);
-}
-
-
 // ===================================================================
 
 void Contact::InitAsDefaultInstance() {
@@ -1425,9 +1374,9 @@ Contact::Contact()
 }
 Contact::Contact(const Contact& from)
   : ::google::protobuf::Message(),
-      _internal_metadata_(NULL) {
+      _internal_metadata_(NULL),
+      phones_(from.phones_) {
   _internal_metadata_.MergeFrom(from._internal_metadata_);
-  phones_.MergeFrom(from.phones_);
   firstname_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   if (from.firstname().size() > 0) {
     firstname_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.firstname_);
@@ -1568,19 +1517,12 @@ bool Contact::MergePartialFromCodedStream(
         break;
       }
 
-      // map<int32, .qtprotobuf.examples.PhoneNumber> phones = 4;
+      // repeated .qtprotobuf.examples.PhoneNumber phones = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
             static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
-          Contact_PhonesEntry_DoNotUse::Parser< ::google::protobuf::internal::MapField<
-              Contact_PhonesEntry_DoNotUse,
-              ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber,
-              ::google::protobuf::internal::WireFormatLite::TYPE_INT32,
-              ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
-              0 >,
-            ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber > > parser(&phones_);
-          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
-              input, &parser));
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_phones()));
         } else {
           goto handle_unusual;
         }
@@ -1667,43 +1609,13 @@ void Contact::SerializeWithCachedSizes(
       3, this->middlename(), output);
   }
 
-  // map<int32, .qtprotobuf.examples.PhoneNumber> phones = 4;
-  if (!this->phones().empty()) {
-    typedef ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::const_pointer
-        ConstPtr;
-    typedef ::google::protobuf::internal::SortItem< ::google::protobuf::int32, ConstPtr > SortItem;
-    typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;
-
-    if (output->IsSerializationDeterministic() &&
-        this->phones().size() > 1) {
-      ::std::unique_ptr<SortItem[]> items(
-          new SortItem[this->phones().size()]);
-      typedef ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::size_type size_type;
-      size_type n = 0;
-      for (::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::const_iterator
-          it = this->phones().begin();
-          it != this->phones().end(); ++it, ++n) {
-        items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);
-      }
-      ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
-      ::std::unique_ptr<Contact_PhonesEntry_DoNotUse> entry;
-      for (size_type i = 0; i < n; i++) {
-        entry.reset(phones_.NewEntryWrapper(
-            items[static_cast<ptrdiff_t>(i)].second->first, items[static_cast<ptrdiff_t>(i)].second->second));
-        ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-            4, *entry, output);
-      }
-    } else {
-      ::std::unique_ptr<Contact_PhonesEntry_DoNotUse> entry;
-      for (::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::const_iterator
-          it = this->phones().begin();
-          it != this->phones().end(); ++it) {
-        entry.reset(phones_.NewEntryWrapper(
-            it->first, it->second));
-        ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-            4, *entry, output);
-      }
-    }
+  // repeated .qtprotobuf.examples.PhoneNumber phones = 4;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->phones_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4,
+      this->phones(static_cast<int>(i)),
+      output);
   }
 
   // .qtprotobuf.examples.Address address = 5;
@@ -1765,47 +1677,12 @@ void Contact::SerializeWithCachedSizes(
         3, this->middlename(), target);
   }
 
-  // map<int32, .qtprotobuf.examples.PhoneNumber> phones = 4;
-  if (!this->phones().empty()) {
-    typedef ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::const_pointer
-        ConstPtr;
-    typedef ::google::protobuf::internal::SortItem< ::google::protobuf::int32, ConstPtr > SortItem;
-    typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;
-
-    if (deterministic &&
-        this->phones().size() > 1) {
-      ::std::unique_ptr<SortItem[]> items(
-          new SortItem[this->phones().size()]);
-      typedef ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::size_type size_type;
-      size_type n = 0;
-      for (::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::const_iterator
-          it = this->phones().begin();
-          it != this->phones().end(); ++it, ++n) {
-        items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);
-      }
-      ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
-      ::std::unique_ptr<Contact_PhonesEntry_DoNotUse> entry;
-      for (size_type i = 0; i < n; i++) {
-        entry.reset(phones_.NewEntryWrapper(
-            items[static_cast<ptrdiff_t>(i)].second->first, items[static_cast<ptrdiff_t>(i)].second->second));
-        target = ::google::protobuf::internal::WireFormatLite::
-                   InternalWriteMessageNoVirtualToArray(
-                       4, *entry, deterministic, target);
-;
-      }
-    } else {
-      ::std::unique_ptr<Contact_PhonesEntry_DoNotUse> entry;
-      for (::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::const_iterator
-          it = this->phones().begin();
-          it != this->phones().end(); ++it) {
-        entry.reset(phones_.NewEntryWrapper(
-            it->first, it->second));
-        target = ::google::protobuf::internal::WireFormatLite::
-                   InternalWriteMessageNoVirtualToArray(
-                       4, *entry, deterministic, target);
-;
-      }
-    }
+  // repeated .qtprotobuf.examples.PhoneNumber phones = 4;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->phones_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        4, this->phones(static_cast<int>(i)), deterministic, target);
   }
 
   // .qtprotobuf.examples.Address address = 5;
@@ -1839,17 +1716,14 @@ size_t Contact::ByteSizeLong() const {
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
         (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
   }
-  // map<int32, .qtprotobuf.examples.PhoneNumber> phones = 4;
-  total_size += 1 *
-      ::google::protobuf::internal::FromIntSize(this->phones_size());
+  // repeated .qtprotobuf.examples.PhoneNumber phones = 4;
   {
-    ::std::unique_ptr<Contact_PhonesEntry_DoNotUse> entry;
-    for (::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >::const_iterator
-        it = this->phones().begin();
-        it != this->phones().end(); ++it) {
-      entry.reset(phones_.NewEntryWrapper(it->first, it->second));
-      total_size += ::google::protobuf::internal::WireFormatLite::
-          MessageSizeNoVirtual(*entry);
+    unsigned int count = static_cast<unsigned int>(this->phones_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->phones(static_cast<int>(i)));
     }
   }
 
@@ -1960,7 +1834,7 @@ void Contact::Swap(Contact* other) {
 }
 void Contact::InternalSwap(Contact* other) {
   using std::swap;
-  phones_.Swap(&other->phones_);
+  CastToBase(&phones_)->InternalSwap(CastToBase(&other->phones_));
   firstname_.Swap(&other->firstname_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
     GetArenaNoVirtual());
   lastname_.Swap(&other->lastname_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
@@ -2707,9 +2581,6 @@ template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::qtprotobuf::examples::Address* A
 template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::qtprotobuf::examples::Job* Arena::CreateMaybeMessage< ::qtprotobuf::examples::Job >(Arena* arena) {
   return Arena::CreateInternal< ::qtprotobuf::examples::Job >(arena);
 }
-template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse* Arena::CreateMaybeMessage< ::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse >(Arena* arena) {
-  return Arena::CreateInternal< ::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse >(arena);
-}
 template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::qtprotobuf::examples::Contact* Arena::CreateMaybeMessage< ::qtprotobuf::examples::Contact >(Arena* arena) {
   return Arena::CreateInternal< ::qtprotobuf::examples::Contact >(arena);
 }

+ 33 - 56
examples/addressbookserver/addressbook.pb.h

@@ -29,9 +29,6 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/repeated_field.h>  // IWYU pragma: export
 #include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/map.h>  // IWYU pragma: export
-#include <google/protobuf/map_entry.h>
-#include <google/protobuf/map_field_inl.h>
 #include <google/protobuf/generated_enum_reflection.h>
 #include <google/protobuf/unknown_field_set.h>
 // @@protoc_insertion_point(includes)
@@ -42,7 +39,7 @@ namespace protobuf_addressbook_2eproto {
 struct TableStruct {
   static const ::google::protobuf::internal::ParseTableField entries[];
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
-  static const ::google::protobuf::internal::ParseTable schema[8];
+  static const ::google::protobuf::internal::ParseTable schema[7];
   static const ::google::protobuf::internal::FieldMetadata field_metadata[];
   static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static const ::google::protobuf::uint32 offsets[];
@@ -57,9 +54,6 @@ extern AddressDefaultTypeInternal _Address_default_instance_;
 class Contact;
 class ContactDefaultTypeInternal;
 extern ContactDefaultTypeInternal _Contact_default_instance_;
-class Contact_PhonesEntry_DoNotUse;
-class Contact_PhonesEntry_DoNotUseDefaultTypeInternal;
-extern Contact_PhonesEntry_DoNotUseDefaultTypeInternal _Contact_PhonesEntry_DoNotUse_default_instance_;
 class Contacts;
 class ContactsDefaultTypeInternal;
 extern ContactsDefaultTypeInternal _Contacts_default_instance_;
@@ -81,7 +75,6 @@ namespace google {
 namespace protobuf {
 template<> ::qtprotobuf::examples::Address* Arena::CreateMaybeMessage<::qtprotobuf::examples::Address>(Arena*);
 template<> ::qtprotobuf::examples::Contact* Arena::CreateMaybeMessage<::qtprotobuf::examples::Contact>(Arena*);
-template<> ::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse* Arena::CreateMaybeMessage<::qtprotobuf::examples::Contact_PhonesEntry_DoNotUse>(Arena*);
 template<> ::qtprotobuf::examples::Contacts* Arena::CreateMaybeMessage<::qtprotobuf::examples::Contacts>(Arena*);
 template<> ::qtprotobuf::examples::Job* Arena::CreateMaybeMessage<::qtprotobuf::examples::Job>(Arena*);
 template<> ::qtprotobuf::examples::ListFrame* Arena::CreateMaybeMessage<::qtprotobuf::examples::ListFrame>(Arena*);
@@ -506,27 +499,6 @@ class Job : public ::google::protobuf::Message /* @@protoc_insertion_point(class
 };
 // -------------------------------------------------------------------
 
-class Contact_PhonesEntry_DoNotUse : public ::google::protobuf::internal::MapEntry<Contact_PhonesEntry_DoNotUse, 
-    ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber,
-    ::google::protobuf::internal::WireFormatLite::TYPE_INT32,
-    ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
-    0 > {
-public:
-  typedef ::google::protobuf::internal::MapEntry<Contact_PhonesEntry_DoNotUse, 
-    ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber,
-    ::google::protobuf::internal::WireFormatLite::TYPE_INT32,
-    ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
-    0 > SuperType;
-  Contact_PhonesEntry_DoNotUse();
-  Contact_PhonesEntry_DoNotUse(::google::protobuf::Arena* arena);
-  void MergeFrom(const Contact_PhonesEntry_DoNotUse& other);
-  static const Contact_PhonesEntry_DoNotUse* internal_default_instance() { return reinterpret_cast<const Contact_PhonesEntry_DoNotUse*>(&_Contact_PhonesEntry_DoNotUse_default_instance_); }
-  void MergeFrom(const ::google::protobuf::Message& other) final;
-  ::google::protobuf::Metadata GetMetadata() const;
-};
-
-// -------------------------------------------------------------------
-
 class Contact : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:qtprotobuf.examples.Contact) */ {
  public:
   Contact();
@@ -562,7 +534,7 @@ class Contact : public ::google::protobuf::Message /* @@protoc_insertion_point(c
                &_Contact_default_instance_);
   }
   static constexpr int kIndexInFileMessages =
-    4;
+    3;
 
   void Swap(Contact* other);
   friend void swap(Contact& a, Contact& b) {
@@ -612,7 +584,6 @@ class Contact : public ::google::protobuf::Message /* @@protoc_insertion_point(c
 
   // nested types ----------------------------------------------------
 
-
   typedef Contact_PhoneType PhoneType;
   static const PhoneType Home =
     Contact_PhoneType_Home;
@@ -645,14 +616,17 @@ class Contact : public ::google::protobuf::Message /* @@protoc_insertion_point(c
 
   // accessors -------------------------------------------------------
 
-  // map<int32, .qtprotobuf.examples.PhoneNumber> phones = 4;
+  // repeated .qtprotobuf.examples.PhoneNumber phones = 4;
   int phones_size() const;
   void clear_phones();
   static const int kPhonesFieldNumber = 4;
-  const ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >&
-      phones() const;
-  ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >*
+  ::qtprotobuf::examples::PhoneNumber* mutable_phones(int index);
+  ::google::protobuf::RepeatedPtrField< ::qtprotobuf::examples::PhoneNumber >*
       mutable_phones();
+  const ::qtprotobuf::examples::PhoneNumber& phones(int index) const;
+  ::qtprotobuf::examples::PhoneNumber* add_phones();
+  const ::google::protobuf::RepeatedPtrField< ::qtprotobuf::examples::PhoneNumber >&
+      phones() const;
 
   // string firstName = 1;
   void clear_firstname();
@@ -724,12 +698,7 @@ class Contact : public ::google::protobuf::Message /* @@protoc_insertion_point(c
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  ::google::protobuf::internal::MapField<
-      Contact_PhonesEntry_DoNotUse,
-      ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber,
-      ::google::protobuf::internal::WireFormatLite::TYPE_INT32,
-      ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
-      0 > phones_;
+  ::google::protobuf::RepeatedPtrField< ::qtprotobuf::examples::PhoneNumber > phones_;
   ::google::protobuf::internal::ArenaStringPtr firstname_;
   ::google::protobuf::internal::ArenaStringPtr lastname_;
   ::google::protobuf::internal::ArenaStringPtr middlename_;
@@ -775,7 +744,7 @@ class Contacts : public ::google::protobuf::Message /* @@protoc_insertion_point(
                &_Contacts_default_instance_);
   }
   static constexpr int kIndexInFileMessages =
-    5;
+    4;
 
   void Swap(Contacts* other);
   friend void swap(Contacts& a, Contacts& b) {
@@ -884,7 +853,7 @@ class SimpleResult : public ::google::protobuf::Message /* @@protoc_insertion_po
                &_SimpleResult_default_instance_);
   }
   static constexpr int kIndexInFileMessages =
-    6;
+    5;
 
   void Swap(SimpleResult* other);
   friend void swap(SimpleResult& a, SimpleResult& b) {
@@ -987,7 +956,7 @@ class ListFrame : public ::google::protobuf::Message /* @@protoc_insertion_point
                &_ListFrame_default_instance_);
   }
   static constexpr int kIndexInFileMessages =
-    7;
+    6;
 
   void Swap(ListFrame* other);
   friend void swap(ListFrame& a, ListFrame& b) {
@@ -1403,8 +1372,6 @@ inline void Job::set_allocated_officeaddress(::qtprotobuf::examples::Address* of
 
 // -------------------------------------------------------------------
 
-// -------------------------------------------------------------------
-
 // Contact
 
 // string firstName = 1;
@@ -1566,22 +1533,34 @@ inline void Contact::set_allocated_middlename(::std::string* middlename) {
   // @@protoc_insertion_point(field_set_allocated:qtprotobuf.examples.Contact.middleName)
 }
 
-// map<int32, .qtprotobuf.examples.PhoneNumber> phones = 4;
+// repeated .qtprotobuf.examples.PhoneNumber phones = 4;
 inline int Contact::phones_size() const {
   return phones_.size();
 }
 inline void Contact::clear_phones() {
   phones_.Clear();
 }
-inline const ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >&
-Contact::phones() const {
-  // @@protoc_insertion_point(field_map:qtprotobuf.examples.Contact.phones)
-  return phones_.GetMap();
+inline ::qtprotobuf::examples::PhoneNumber* Contact::mutable_phones(int index) {
+  // @@protoc_insertion_point(field_mutable:qtprotobuf.examples.Contact.phones)
+  return phones_.Mutable(index);
 }
-inline ::google::protobuf::Map< ::google::protobuf::int32, ::qtprotobuf::examples::PhoneNumber >*
+inline ::google::protobuf::RepeatedPtrField< ::qtprotobuf::examples::PhoneNumber >*
 Contact::mutable_phones() {
-  // @@protoc_insertion_point(field_mutable_map:qtprotobuf.examples.Contact.phones)
-  return phones_.MutableMap();
+  // @@protoc_insertion_point(field_mutable_list:qtprotobuf.examples.Contact.phones)
+  return &phones_;
+}
+inline const ::qtprotobuf::examples::PhoneNumber& Contact::phones(int index) const {
+  // @@protoc_insertion_point(field_get:qtprotobuf.examples.Contact.phones)
+  return phones_.Get(index);
+}
+inline ::qtprotobuf::examples::PhoneNumber* Contact::add_phones() {
+  // @@protoc_insertion_point(field_add:qtprotobuf.examples.Contact.phones)
+  return phones_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::qtprotobuf::examples::PhoneNumber >&
+Contact::phones() const {
+  // @@protoc_insertion_point(field_list:qtprotobuf.examples.Contact.phones)
+  return phones_;
 }
 
 // .qtprotobuf.examples.Address address = 5;
@@ -1791,8 +1770,6 @@ inline void ListFrame::set_end(::google::protobuf::int32 value) {
 
 // -------------------------------------------------------------------
 
-// -------------------------------------------------------------------
-
 
 // @@protoc_insertion_point(namespace_scope)
 

+ 65 - 21
examples/addressbookserver/main.cpp

@@ -1,14 +1,18 @@
 #include <iostream>
+#include <vector>
 #include <grpc++/grpc++.h>
 #include "addressbook.pb.h"
 #include "addressbook.grpc.pb.h"
+using namespace ::qtprotobuf::examples;
 
-class AddressBookService final : public qtprotobuf::examples::AddressBook::Service {
-    ::qtprotobuf::examples::Contacts m_contacts;
+class ContactsHandler;
+
+class AddressBookService final : public AddressBook::WithAsyncMethod_contacts<AddressBook::Service> {
 public:
-    AddressBookService() {
-        std::cout << "getContacts called" << std::endl;
-        ::qtprotobuf::examples::Contact* contact = m_contacts.add_list();
+    Contacts m_contacts;
+    std::vector<::grpc::ServerAsyncWriter<Contacts> *> m_clients;
+    AddressBookService(): m_clients({}) {
+        Contact* contact = m_contacts.add_list();
         contact->set_firstname("John");
         contact->set_lastname("Doe");
         contact = m_contacts.add_list();
@@ -23,45 +27,72 @@ public:
         contact = m_contacts.add_list();
         contact->set_firstname("Ebenezer");
         contact->set_lastname("Scrooge");
-        ::qtprotobuf::examples::Job *job = new ::qtprotobuf::examples::Job;
+        Job *job = new Job;
         job->set_title("Job title");
         contact->set_allocated_job(job);
-        ::qtprotobuf::examples::PhoneNumber home;
-        home.set_countrycode(49);
-        home.set_number(12324534679);
-        (*contact->mutable_phones())[::qtprotobuf::examples::Contact::Home] = home;
+        PhoneNumber *home = (*contact->mutable_phones()).Add();
+        home->set_countrycode(49);
+        home->set_number(12324534679);
     }
+
     ~AddressBookService() {}
-    ::grpc::Status addContact(::grpc::ServerContext* context, const ::qtprotobuf::examples::Contact* request, ::qtprotobuf::examples::Contacts* response) override
+
+    void updateContacts() {
+        for(int i = 0; i < (m_clients.size() - 1); i++) {
+            m_clients[i]->Write(m_contacts, nullptr);
+        }
+    }
+
+    void registerWriter(ContactsHandler *handler);
+
+    ::grpc::Status addContact(::grpc::ServerContext* context, const Contact* request, Contacts* response) override
     {
         std::cout << "addContact called" << std::endl;
-        ::qtprotobuf::examples::Contact* newContact = m_contacts.add_list();
+        Contact* newContact = m_contacts.add_list();
         *newContact = *request;
         *response = m_contacts;
+        updateContacts();
         return ::grpc::Status();
     }
-    ::grpc::Status removeContact(::grpc::ServerContext* context, const ::qtprotobuf::examples::Contact* request, ::qtprotobuf::examples::Contacts* response) override
+    ::grpc::Status removeContact(::grpc::ServerContext* context, const Contact* request, Contacts* response) override
     {
         std::cout << "removeContact called" << std::endl;
+        updateContacts();
         return ::grpc::Status(::grpc::UNIMPLEMENTED, "Unimplemented");
     }
-    ::grpc::Status getContacts(::grpc::ServerContext* context, const ::qtprotobuf::examples::ListFrame* request, ::qtprotobuf::examples::Contacts* response) override
-    {
-        *response = m_contacts;
-        return ::grpc::Status();
-    }
-    ::grpc::Status makeCall(::grpc::ServerContext* context, const ::qtprotobuf::examples::Contact* request, ::qtprotobuf::examples::SimpleResult* response) override
+    ::grpc::Status makeCall(::grpc::ServerContext* context, const Contact* request, SimpleResult* response) override
     {
         std::cout << "makeCall called" << std::endl;
         return ::grpc::Status(::grpc::UNIMPLEMENTED, "Unimplemented");
     }
-    ::grpc::Status navigateTo(::grpc::ServerContext* context, const ::qtprotobuf::examples::Address* request, ::qtprotobuf::examples::SimpleResult* response) override
+    ::grpc::Status navigateTo(::grpc::ServerContext* context, const Address* request, SimpleResult* response) override
     {
         std::cout << "navigateTo called" << std::endl;
         return ::grpc::Status(::grpc::UNIMPLEMENTED, "Unimplemented");
     }
 };
 
+class ContactsHandler {
+public:
+    ContactsHandler(AddressBookService* service, ::grpc::ServerCompletionQueue* cq) :  tag_(0xdeadbeef)
+      , writer_(&ctx_)
+      , cq_(cq)
+    {
+        service->Requestcontacts(&ctx_, &request_, &writer_, cq_, cq_, &tag_);
+        service->registerWriter(this);
+    }
+    int tag_;
+    grpc::ServerContext ctx_;
+    ListFrame request_;
+    ::grpc::ServerAsyncWriter< ::qtprotobuf::examples::Contacts> writer_;
+    ::grpc::ServerCompletionQueue* cq_;
+};
+
+
+void AddressBookService::registerWriter(ContactsHandler *handler)    {
+    m_clients.push_back(&(handler->writer_));
+}
+
 int main(int argc, char *argv[])
 {
     std::string server_address("localhost:65001");
@@ -70,7 +101,20 @@ int main(int argc, char *argv[])
     grpc::ServerBuilder builder;
     builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
     builder.RegisterService(&service);
+    std::unique_ptr<grpc::ServerCompletionQueue> cq = builder.AddCompletionQueue();
     std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
     std::cout << "Server listening on " << server_address << std::endl;
-    server->Wait();
+    ContactsHandler *last = new ContactsHandler(&service, cq.get());
+    while (true) {
+        int *tag;
+        bool ok;
+        cq->Next((void**)&tag, &ok);
+        if (tag == nullptr) {
+            continue;
+        }
+        if ((*tag) == 0xdeadbeef) {
+            last->writer_.Write(service.m_contacts, nullptr);
+            last = new ContactsHandler(&service, cq.get());
+        }
+    }
 }