1 // server.cpp : Defines the entry point for the console application.
2 //
3 // sample server command line app using Thrift IPC.
4 //
5 // This is a simple demonstration of full duplex RPC. That is, each
6 // side runs both a client and server to enable bidirectional event
7 // signaling.
8 //
9 
10 #ifdef _WIN32
11 #  include "stdafx.h"
12 #else
13 #  include "config.h"
14 #endif
15 
16 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17 //Include this before the generated includes
18 #include "ThriftCommon.h"
19 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 //Tailor these to your generated files
21 #include "../gen-cpp/SampleService.h"
22 #include "../gen-cpp/SampleCallback.h"
23 
24 using namespace Sample; //declared in .thrift file
25 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 
27 int16_t ClientPort_;
28 std::string ClientPipeName_;
29 void S2CThreadProc();
30 
31 //-----------------------------------------------------------------------------
32 // RPC implementations
33 //
34 class SampleServiceHandler : virtual public SampleServiceIf {
35  public:
SampleServiceHandler()36   SampleServiceHandler() {
37     // Your initialization goes here
38   }
39 
HelloThere(std::string & _return,const std::string & HelloString)40   void HelloThere(std::string& _return, const std::string& HelloString) {
41     // Your implementation goes here
42     printf("<<<HelloThere() received string: %s\n", HelloString.c_str());
43 	_return = "Good thank you.";
44   }
45 
ServerDoSomething()46   void ServerDoSomething() {
47     // Your implementation goes here
48     printf("ServerDoSomething(): Simulating work for 5 seconds\n");
49     Sleep(5000);
50     printf("ServerDoSomething(): Done\n");
51   }
52 
ClientSideListenPort(const int16_t ClientListenPort)53   void ClientSideListenPort(const int16_t ClientListenPort)
54   {
55 	ClientPort_ = ClientListenPort;
56 	ClientPipeName_ = "";
57 #ifdef _WIN32
58 	printf(">>>Connecting to client on port %d\n", ClientPort_);
59 	boost::thread Connect2ClientThread(S2CThreadProc);
60 #endif
61   }
62 
ClientSidePipeName(const std::string & ClientPipeName)63   void ClientSidePipeName(const std::string& ClientPipeName)
64   {
65 	ClientPipeName_ = ClientPipeName;
66 	ClientPort_ = 0;
67 #ifdef _WIN32
68 	printf(">>>Connecting to client pipe %s\n", ClientPipeName_.c_str());
69 	boost::thread Connect2ClientThread(S2CThreadProc);
70 #endif
71   }
72 };
73 //-----------------------------------------------------------------------------
74 
75 #ifdef _WIN32
_tmain(int argc,_TCHAR * argv[])76 int _tmain(int argc, _TCHAR* argv[])
77 #else
78 int main(int argc, char **argv)
79 #endif
80 {
81 	int port;
82 	std::string pipename; //e.g. "affpipe"
83 
84 	bool usage = false;
85 
86 	//Process command line params
87 	if(argc > 1)
88 	{
89 		if(_tcscmp(argv[1], TEXT("-sp")) == 0)
90 		{	//Socket Port specified
91 			port = _tstoi(argv[2]);
92 #ifdef _WIN32
93 			TWinsockSingleton::create();
94 #endif
95 			// Start the thrift server which is a blocking call.
96 			thriftcommon::RunThriftServer<SampleServiceHandler, SampleServiceProcessor>(10, port);
97 		}
98 		else if(_tcscmp(argv[1], TEXT("-np")) == 0)
99 		{	//Named Pipe specified
100 #ifdef _WIN32
101 			std::wstring wpipe(argv[2]);
102 			pipename.resize(wpipe.length());
103 			std::copy(wpipe.begin(), wpipe.end(), pipename.begin());
104 #else
105 			pipename = argv[2];
106 #endif
107 			printf("Using Named Pipe %s\n", pipename.c_str());
108 
109 			//Thrift over Named Pipe.
110 			thriftcommon::RunThriftServer<SampleServiceHandler, SampleServiceProcessor>(10, pipename);
111 		}
112 		else if(_tcscmp(argv[1], TEXT("-ap")) == 0)
113 		{	//Anonymous Pipe specified
114 			//This is more involved because the child needs to be launched
115 			//after the transport is created but before the blocking server
116 			//call.
117 #ifdef _WIN32
118 			boost::shared_ptr<TServerTransport> transport(new TPipeServer()); //Anonymous pipe
119 			thriftcommon::LaunchAnonPipeChild(".\\client.exe", transport);
120 			boost::shared_ptr<SampleServiceHandler> handler(new SampleServiceHandler());
121 			thriftcommon::RunThriftServer<SampleServiceHandler, SampleServiceProcessor>(handler, 10, transport);
122 #else
123 			printf("Anonymous pipes not (yet) supported under *NIX\n");
124 #endif
125 		}
126 		else
127 			usage = true;
128 	}
129 	else
130 		usage = true;
131 
132 	if(usage)
133 	{
134 		printf("Thrift sample server usage:\n\n");
135 		printf("Socket Port :   -sp <port#>\n");
136 		printf("Named Pipe :    -np <pipename> (e.g. affpipe)\n");
137 		printf("Anonymous Pipe: -ap\n");
138 	}
139 	return 0;
140 }
141 
142 
143 //Thread Routine that connects to the 'client'.
S2CThreadProc()144 void S2CThreadProc()
145 {
146 	//Master server's connection to client-side's server.
147 	boost::shared_ptr<SampleCallbackClient> clientsrv; //Client class from Thrift-generated code.
148 	boost::shared_ptr<TTransport> transport;
149 	if(ClientPort_ != 0)
150 		thriftcommon::ConnectToServer<SampleCallbackClient, TTransport>(clientsrv, transport, ClientPort_);
151 	if(!ClientPipeName_.empty())
152 		thriftcommon::ConnectToServer<SampleCallbackClient, TTransport>(clientsrv, transport, ClientPipeName_);
153 
154 	try {
155 		transport->open();
156 
157 		clientsrv->pingclient();
158 		Sleep(1500);
159 		clientsrv->pingclient();
160 		Sleep(1500);
161 		clientsrv->pingclient();
162 
163 		transport->close();
164 	} catch (TException &tx) {
165 		printf("ERROR: %s\n", tx.what());
166 	}
167 }
168 
169