1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <Ice/Ice.h>
6 #include <TestHelper.h>
7 #include <Test.h>
8
9 using namespace std;
10 using namespace Ice;
11 using namespace Test;
12
13 class PingReplyI : public PingReply, public IceUtil::Monitor<IceUtil::Mutex>
14 {
15 public:
16
17 virtual void
reply(const Ice::Current &)18 reply(const Ice::Current&)
19 {
20 Lock sync(*this);
21 ++_replies;
22 notify();
23 }
24
25 void
reset()26 reset()
27 {
28 _replies = 0;
29 }
30
31 bool
waitReply(int expectedReplies,const IceUtil::Time & timeout)32 waitReply(int expectedReplies, const IceUtil::Time& timeout)
33 {
34 Lock sync(*this);
35 IceUtil::Time end = IceUtil::Time::now() + timeout;
36 while(_replies < expectedReplies)
37 {
38 IceUtil::Time delay = end - IceUtil::Time::now();
39 if(delay > IceUtil::Time::seconds(0))
40 {
41 timedWait(delay);
42 }
43 else
44 {
45 break;
46 }
47 }
48 return _replies == expectedReplies;
49 }
50
51 private:
52
53 int _replies;
54 };
55 ICE_DEFINE_PTR(PingReplyIPtr, PingReplyI);
56
57 void
allTests(Test::TestHelper * helper)58 allTests(Test::TestHelper* helper)
59 {
60 Ice::CommunicatorPtr communicator = helper->communicator();
61 communicator->getProperties()->setProperty("ReplyAdapter.Endpoints", "udp");
62 Ice::ObjectAdapterPtr adapter = communicator->createObjectAdapter("ReplyAdapter");
63 PingReplyIPtr replyI = ICE_MAKE_SHARED(PingReplyI);
64 PingReplyPrxPtr reply = ICE_UNCHECKED_CAST(PingReplyPrx, adapter->addWithUUID(replyI))->ice_datagram();
65 adapter->activate();
66
67 cout << "testing udp... " << flush;
68 ObjectPrxPtr base = communicator->stringToProxy("test -d:" + helper->getTestEndpoint("udp"));
69 TestIntfPrxPtr obj = ICE_UNCHECKED_CAST(TestIntfPrx, base);
70
71 int nRetry = 5;
72 bool ret = false;
73 while(nRetry-- > 0)
74 {
75 replyI->reset();
76 obj->ping(reply);
77 obj->ping(reply);
78 obj->ping(reply);
79 ret = replyI->waitReply(3, IceUtil::Time::seconds(2));
80 if(ret)
81 {
82 break; // Success
83 }
84
85 // If the 3 datagrams were not received within the 2 seconds, we try again to
86 // receive 3 new datagrams using a new object. We give up after 5 retries.
87 replyI = ICE_MAKE_SHARED(PingReplyI);
88 reply = ICE_UNCHECKED_CAST(PingReplyPrx, adapter->addWithUUID(replyI))->ice_datagram();
89 }
90 test(ret);
91
92 if(communicator->getProperties()->getPropertyAsInt("Ice.Override.Compress") == 0)
93 {
94 //
95 // Only run this test if compression is disabled, the test expect fixed message size
96 // to be sent over the wire.
97 //
98
99 Test::ByteSeq seq;
100 try
101 {
102 seq.resize(1024);
103 while(true)
104 {
105 seq.resize(seq.size() * 2 + 10);
106 replyI->reset();
107 obj->sendByteSeq(seq, reply);
108 replyI->waitReply(1, IceUtil::Time::seconds(10));
109 }
110 }
111 catch(const DatagramLimitException&)
112 {
113 test(seq.size() > 16384);
114 }
115 obj->ice_getConnection()->close(ICE_SCOPED_ENUM(ConnectionClose, GracefullyWithWait));
116 communicator->getProperties()->setProperty("Ice.UDP.SndSize", "64000");
117 seq.resize(50000);
118 try
119 {
120 replyI->reset();
121 obj->sendByteSeq(seq, reply);
122 test(!replyI->waitReply(1, IceUtil::Time::milliSeconds(500)));
123 }
124 catch(const Ice::LocalException& ex)
125 {
126 cerr << ex << endl;
127 test(false);
128 }
129 }
130
131 cout << "ok" << endl;
132
133 ostringstream endpoint;
134 if(communicator->getProperties()->getProperty("Ice.IPv6") == "1")
135 {
136 endpoint << "udp -h \"ff15::1:1\" -p " << helper->getTestPort(10);
137 #if defined(__APPLE__) || defined(_WIN32)
138 endpoint << " --interface \"::1\""; // Use loopback to prevent other machines to answer. the multicast requests.
139 #endif
140 }
141 else
142 {
143 endpoint << "udp -h 239.255.1.1 -p " << helper->getTestPort(10);
144 #if defined(__APPLE__) || defined(_WIN32)
145 endpoint << " --interface 127.0.0.1"; // Use loopback to prevent other machines to answer.
146 #endif
147 }
148 base = communicator->stringToProxy("test -d:" + endpoint.str());
149 TestIntfPrxPtr objMcast = ICE_UNCHECKED_CAST(TestIntfPrx, base);
150 #if (!defined(__APPLE__) || (defined(__APPLE__) && !TARGET_OS_IPHONE))
151 cout << "testing udp multicast... " << flush;
152
153 nRetry = 5;
154 while(nRetry-- > 0)
155 {
156 replyI->reset();
157 objMcast->ping(reply);
158 ret = replyI->waitReply(5, IceUtil::Time::seconds(2));
159 if(ret)
160 {
161 break; // Success
162 }
163 replyI = ICE_MAKE_SHARED(PingReplyI);
164 reply = ICE_UNCHECKED_CAST(PingReplyPrx, adapter->addWithUUID(replyI))->ice_datagram();
165 }
166 if(!ret)
167 {
168 cout << "failed (is a firewall enabled?)" << endl;
169 }
170 else
171 {
172 cout << "ok" << endl;
173 }
174 #endif
175
176 cout << "testing udp bi-dir connection... " << flush;
177 obj->ice_getConnection()->setAdapter(adapter);
178 objMcast->ice_getConnection()->setAdapter(adapter);
179 nRetry = 5;
180 while(nRetry-- > 0)
181 {
182 replyI->reset();
183 obj->pingBiDir(reply->ice_getIdentity());
184 obj->pingBiDir(reply->ice_getIdentity());
185 obj->pingBiDir(reply->ice_getIdentity());
186 ret = replyI->waitReply(3, IceUtil::Time::seconds(2));
187 if(ret)
188 {
189 break; // Success
190 }
191
192 // If the 3 datagrams were not received within the 2 seconds, we try again to
193 // receive 3 new datagrams using a new object. We give up after 5 retries.
194 replyI = ICE_MAKE_SHARED(PingReplyI);
195 reply = ICE_UNCHECKED_CAST(PingReplyPrx, adapter->addWithUUID(replyI))->ice_datagram();
196 }
197 test(ret);
198 cout << "ok" << endl;
199
200 //
201 // Sending the replies back on the multicast UDP connection doesn't work for most
202 // platform (it works for macOS Leopard but not Snow Leopard, doesn't work on SLES,
203 // Windows...). For Windows, see UdpTransceiver constructor for the details. So
204 // we don't run this test.
205 //
206 // cout << "testing udp bi-dir connection... " << flush;
207 // nRetry = 5;
208 // while(nRetry-- > 0)
209 // {
210 // replyI->reset();
211 // objMcast->pingBiDir(reply->ice_getIdentity());
212 // ret = replyI->waitReply(5, IceUtil::Time::seconds(2));
213 // if(ret)
214 // {
215 // break; // Success
216 // }
217 // replyI = new PingReplyI;
218 // reply = PingReplyPrx::uncheckedCast(adapter->addWithUUID(replyI))->ice_datagram();
219 // }
220 // if(!ret)
221 // {
222 // cout << "failed (is a firewall enabled?)" << endl;
223 // }
224 // else
225 // {
226 // cout << "ok" << endl;
227 // }
228 }
229