-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c552627
commit 9d0cb9e
Showing
12 changed files
with
331 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
cmake_minimum_required(VERSION 3.16) | ||
|
||
project(greeter CXX) | ||
|
||
include(../../cmake/common.cmake) | ||
|
||
add_executable(client Client.cpp Greeter.ice) | ||
slice2cpp_generate(client) | ||
target_link_libraries(client Ice::Ice) | ||
|
||
add_executable(server Server.cpp Chatbot.cpp Chatbot.h Greeter.ice) | ||
slice2cpp_generate(server) | ||
target_link_libraries(server Ice::Ice) | ||
|
||
add_executable(forwardingserver Forwarder.cpp Forwarder.h ForwardingServer.cpp) | ||
target_link_libraries(forwardingserver Ice::Ice) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#include "Chatbot.h" | ||
|
||
#include <iostream> | ||
#include <sstream> | ||
|
||
using namespace std; | ||
|
||
string | ||
Server::Chatbot::greet(string name, const Ice::Current&) | ||
{ | ||
cout << "Dispatching greet request { name = '" << name << "' }" << endl; | ||
|
||
ostringstream os; | ||
os << "Hello, " << name << "!"; | ||
return os.str(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#ifndef CHATBOT_H | ||
#define CHATBOT_H | ||
|
||
#include "Greeter.h" | ||
|
||
namespace Server | ||
{ | ||
/// Chatbot is an Ice servant that implements Slice interface Greeter. | ||
class Chatbot : public VisitorCenter::Greeter | ||
{ | ||
public: | ||
// Implements the pure virtual function in the base class (VisitorCenter::Greeter) generated by the Slice | ||
// compiler. | ||
std::string greet(std::string name, const Ice::Current&) override; | ||
}; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#include "Greeter.h" | ||
|
||
#include <cstdlib> | ||
#include <iostream> | ||
|
||
using namespace std; | ||
|
||
int | ||
main(int argc, char* argv[]) | ||
{ | ||
// Figure out my name. | ||
const char* name = getenv("USER"); | ||
if (name == nullptr) | ||
{ | ||
name = getenv("USERNAME"); | ||
} | ||
if (name == nullptr) | ||
{ | ||
name = "masked user"; | ||
} | ||
|
||
// Create an Ice communicator to initialize the Ice runtime. | ||
const Ice::CommunicatorHolder communicatorHolder{argc, argv}; | ||
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator(); | ||
|
||
// We create a Greeter proxy for a Greeter object in the Forwarder server (port 10000). | ||
VisitorCenter::GreeterPrx greeter{communicator, "greeter:tcp -h localhost -p 10000"}; | ||
|
||
// Send a request to the remote object and wait for the response. | ||
string greeting = greeter->greet(name); | ||
cout << greeting << endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#include "Forwarder.h" | ||
|
||
using namespace std; | ||
|
||
ForwardingServer::Forwarder::Forwarder(Ice::ObjectPrx targetTemplate) : _targetTemplate{std::move(targetTemplate)} {} | ||
|
||
void | ||
ForwardingServer::Forwarder::dispatch(Ice::IncomingRequest& request, function<void(Ice::OutgoingResponse)> sendResponse) | ||
{ | ||
// Make a copy of the current object carried by the request. | ||
const Ice::Current current{request.current()}; | ||
|
||
// Create a proxy with the the desired identity and facet. | ||
Ice::ObjectPrx target = _targetTemplate.ice_identity(current.id).ice_facet(current.facet); | ||
|
||
if (current.requestId == 0) | ||
{ | ||
// The incoming request is one-way, so we reconfigure target to be one-way. | ||
target = target.ice_oneway(); | ||
} | ||
|
||
// Read the encapsulation containing the in-parameters. | ||
const std::byte* inEncapsulationStart = nullptr; | ||
int32_t inEncapsulationSize = 0; | ||
request.inputStream().readEncapsulation(inEncapsulationStart, inEncapsulationSize); | ||
|
||
// Make the invocation asynchronously. This call reports most exceptions through its exception callback. | ||
target.ice_invokeAsync( | ||
current.operation, | ||
current.mode, | ||
make_pair(inEncapsulationStart, inEncapsulationStart + inEncapsulationSize), | ||
[sendResponse, current](bool ok, pair<const std::byte*, const std::byte*> outEncapsulation) | ||
{ | ||
// The response callback is executed by a thread from the Ice client thread pool when the invocation | ||
// completes successfully (ok is true) or with a user exception (ok is false). | ||
// We create an OutgoingResponse object and send it back to the client with sendResponse. | ||
sendResponse(Ice::makeOutgoingResponse(ok, outEncapsulation, current)); | ||
}, | ||
[sendResponse, current](std::exception_ptr exceptionPtr) | ||
{ | ||
// The exception callback. | ||
// We create an OutgoingResponse object with the exception and send it back to the client with | ||
// sendResponse. If the exception is an Ice local exception that cannot be marshaled, such as | ||
// Ice::ConnectionRefusedException, makeOutgoingResponse marshals an Ice::UnknownLocalException. | ||
sendResponse(Ice::makeOutgoingResponse(exceptionPtr, current)); | ||
}, | ||
nullptr, // no sent callback | ||
current.ctx); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#ifndef FORWARDER_H | ||
#define FORWARDER_H | ||
|
||
#include <Ice/Ice.h> | ||
|
||
namespace ForwardingServer | ||
{ | ||
/// Forwarder is an Ice servant that implements Ice::Object by forwarding all requests it receives to a remote | ||
/// Ice object. | ||
class Forwarder final : public Ice::Object | ||
{ | ||
public: | ||
/// Constructs a Forwarder servant. | ||
/// @param targetTemplate A template for the target proxy. | ||
explicit Forwarder(Ice::ObjectPrx targetTemplate); | ||
|
||
// Implements the pure virtual function dispatch declared on Ice::Object. | ||
void dispatch(Ice::IncomingRequest& request, std::function<void(Ice::OutgoingResponse)> sendResponse) final; | ||
|
||
private: | ||
Ice::ObjectPrx _targetTemplate; | ||
}; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#include "Forwarder.h" | ||
|
||
#include <iostream> | ||
|
||
using namespace std; | ||
|
||
int | ||
main(int argc, char* argv[]) | ||
{ | ||
// CtrlCHandler is a helper class that handles Ctrl+C and similar signals. It must be constructed at the beginning | ||
// of the program, before creating an Ice communicator or starting any thread. | ||
Ice::CtrlCHandler ctrlCHandler; | ||
|
||
// Create an Ice communicator to initialize the Ice runtime. The CommunicatorHolder is a RAII helper that creates | ||
// the communicator in its constructor and destroys it when it goes out of scope. | ||
const Ice::CommunicatorHolder communicatorHolder{argc, argv}; | ||
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator(); | ||
|
||
// Create an object adapter that listens for incoming requests and dispatches them to servants. | ||
auto adapter = communicator->createObjectAdapterWithEndpoints("ForwarderAdapter", "tcp -p 10000"); | ||
|
||
// Create a target proxy template, with a dummy identity. | ||
Ice::ObjectPrx targetTemplate{communicator, "dummy:tcp -h localhost -p 4061"}; | ||
|
||
// Register the Forwarder servant as default servant with the object adapter. The empty category means this default | ||
// servant receives requests to all Ice objects. | ||
adapter->addDefaultServant(make_shared<ForwardingServer::Forwarder>(targetTemplate), ""); | ||
|
||
// Start dispatching requests. | ||
adapter->activate(); | ||
cout << "Listening on port 10000..." << endl; | ||
|
||
// Wait until the user presses Ctrl+C. | ||
int signal = ctrlCHandler.wait(); | ||
cout << "Caught signal " << signal << ", exiting..." << endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#pragma once | ||
|
||
module VisitorCenter | ||
{ | ||
/// Represents a simple greeter. | ||
interface Greeter | ||
{ | ||
/// Creates a personalized greeting. | ||
/// @param name The name of the person to greet. | ||
/// @return The greeting. | ||
string greet(string name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Forwarder | ||
|
||
The Forwarder demo shows how to write a servant that forwards all requests it receives to another remote Ice object, | ||
as-is. | ||
|
||
The core of this demo is the generic Forwarding server. This server listens on tcp port 10000 and forwards all | ||
requests to tcp port 4061 on the same host. | ||
|
||
The demo also includes a Greeter client and server; these are the usual Greeter client and server, except the client | ||
is configured to use port 10000: | ||
|
||
```mermaid | ||
flowchart LR | ||
c[Greeter Client] --> f[Forwarding Server:10000] --> s[Greeter Server:4061] | ||
``` | ||
|
||
The Forwarding server is generic can be inserted between any client and server. In particular, the Forwarding server | ||
does not use any Slice generated code. | ||
|
||
To build the demo, run: | ||
|
||
```shell | ||
cmake -B build | ||
cmake --build build --config Release | ||
``` | ||
|
||
The build produces 3 executables: client, server, and forwardingserver. | ||
|
||
To run the demo, first start the server and the forwarding server in separate terminals: | ||
|
||
**Linux/macOS:** | ||
|
||
```shell | ||
./build/server --Ice.Trace.Dispatch | ||
``` | ||
|
||
```shell | ||
./build/forwardingserver --Ice.Trace.Dispatch | ||
``` | ||
|
||
**Windows:** | ||
|
||
```shell | ||
build\Release\server --Ice.Trace.Dispatch | ||
``` | ||
|
||
```shell | ||
build\Release\forwardingserver --Ice.Trace.Dispatch | ||
``` | ||
|
||
In a third terminal, start the client: | ||
|
||
**Linux/macOS:** | ||
|
||
```shell | ||
./build/client --Ice.Trace.Network | ||
``` | ||
|
||
**Windows:** | ||
|
||
```shell | ||
build\Release\client --Ice.Trace.Network | ||
``` | ||
|
||
> [!NOTE] | ||
> The `--Ice.Trace` command-line options are optional: they turn-on tracing (logging) for request dispatches | ||
> (`--Ice.Trace.Dispatch`) and connection establishment/closure (`--Ice.Trace.Network`) and help you follow the call | ||
> flow. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#include "Chatbot.h" | ||
|
||
#include <iostream> | ||
|
||
using namespace std; | ||
|
||
int | ||
main(int argc, char* argv[]) | ||
{ | ||
// CtrlCHandler is a helper class that handles Ctrl+C and similar signals. It must be constructed at the beginning | ||
// of the program, before creating an Ice communicator or starting any thread. | ||
Ice::CtrlCHandler ctrlCHandler; | ||
|
||
// Create an Ice communicator to initialize the Ice runtime. The CommunicatorHolder is a RAII helper that creates | ||
// the communicator in its constructor and destroys it when it goes out of scope. | ||
const Ice::CommunicatorHolder communicatorHolder{argc, argv}; | ||
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator(); | ||
|
||
// Create an object adapter that listens for incoming requests and dispatches them to servants. | ||
auto adapter = communicator->createObjectAdapterWithEndpoints("GreeterAdapter", "tcp -p 4061"); | ||
|
||
// Register the Chatbot servant with the adapter. | ||
adapter->add(make_shared<Server::Chatbot>(), Ice::stringToIdentity("greeter")); | ||
|
||
// Start dispatching requests. | ||
adapter->activate(); | ||
cout << "Listening on port 4061..." << endl; | ||
|
||
// Wait until the user presses Ctrl+C. | ||
int signal = ctrlCHandler.wait(); | ||
cout << "Caught signal " << signal << ", exiting..." << endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters