1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Ice/IncomingAsync.h>
6 #include <Ice/ServantLocator.h>
7 #include <Ice/Object.h>
8 #include <Ice/ConnectionI.h>
9 #include <Ice/LocalException.h>
10 #include <Ice/Protocol.h>
11 #include <Ice/Instance.h>
12 #include <Ice/Properties.h>
13 #include <Ice/ReplyStatus.h>
14 #include <IceUtil/Mutex.h>
15 #include <IceUtil/MutexPtrLock.h>
16 
17 using namespace std;
18 using namespace Ice;
19 using namespace IceInternal;
20 
21 #ifndef ICE_CPP11_MAPPING
upCast(IncomingAsync * p)22 IceUtil::Shared* IceInternal::upCast(IncomingAsync* p) { return p; }
upCast(AMD_Object_ice_invoke * p)23 IceUtil::Shared* Ice::upCast(AMD_Object_ice_invoke* p) { return p; }
24 
~AMDCallback()25 Ice::AMDCallback::~AMDCallback()
26 {
27     // Out of line to avoid weak vtable
28 }
29 
~AMD_Object_ice_invoke()30 Ice::AMD_Object_ice_invoke::~AMD_Object_ice_invoke()
31 {
32     // Out of line to avoid weak vtable
33 }
34 #endif
35 
36 namespace
37 {
38 
39 IceUtil::Mutex* globalMutex = 0;
40 
41 class Init
42 {
43 public:
44 
Init()45     Init()
46     {
47         globalMutex = new IceUtil::Mutex;
48     }
49 
~Init()50     ~Init()
51     {
52         delete globalMutex;
53         globalMutex = 0;
54     }
55 };
56 
57 Init init;
58 
59 }
60 
IncomingAsync(Incoming & in)61 IceInternal::IncomingAsync::IncomingAsync(Incoming& in) :
62     IncomingBase(in),
63     _responseSent(false),
64     _responseHandlerCopy(ICE_GET_SHARED_FROM_THIS(_responseHandler))
65 {
66 #ifndef ICE_CPP11_MAPPING
67     in.setAsync(this);
68 #endif
69 }
70 
71 #ifdef ICE_CPP11_MAPPING
72 shared_ptr<IncomingAsync>
create(Incoming & in)73 IceInternal::IncomingAsync::create(Incoming& in)
74 {
75     auto async = make_shared<IncomingAsync>(in);
76     in.setAsync(async);
77     return async;
78 }
79 #endif
80 
81 #ifndef ICE_CPP11_MAPPING
82 void
ice_exception(const::std::exception & exc)83 IceInternal::IncomingAsync::ice_exception(const ::std::exception& exc)
84 {
85     try
86     {
87         for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
88         {
89             if(!(*p)->exception(exc))
90             {
91                 return;
92             }
93         }
94     }
95     catch(...)
96     {
97         return;
98     }
99 
100     checkResponseSent();
101     IncomingBase::exception(exc, true); // User thread
102 }
103 
104 void
ice_exception()105 IceInternal::IncomingAsync::ice_exception()
106 {
107     try
108     {
109         for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
110         {
111             if(!(*p)->exception())
112             {
113                 return;
114             }
115         }
116     }
117     catch(...)
118     {
119         return;
120     }
121 
122     checkResponseSent();
123     IncomingBase::exception("unknown c++ exception", true); // User thread
124 }
125 
126 #endif
127 
128 void
kill(Incoming & in)129 IceInternal::IncomingAsync::kill(Incoming& in)
130 {
131     checkResponseSent();
132     in._observer.adopt(_observer); // Give back the observer to incoming.
133 }
134 
135 void
completed()136 IceInternal::IncomingAsync::completed()
137 {
138     for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
139     {
140         try
141         {
142 #ifdef ICE_CPP11_MAPPING
143             if(p->first && !p->first())
144 #else
145             if(!(*p)->response())
146 #endif
147             {
148                 return;
149             }
150         }
151         catch(...)
152         {
153         }
154     }
155 
156     checkResponseSent();
157     IncomingBase::response(true); // User thread
158 }
159 
160 #ifdef ICE_CPP11_MAPPING
161 void
completed(exception_ptr ex)162 IceInternal::IncomingAsync::completed(exception_ptr ex)
163 {
164     for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
165     {
166         try
167         {
168             if(p->second && !p->second(ex))
169             {
170                 return;
171             }
172         }
173         catch(...)
174         {
175         }
176     }
177 
178     checkResponseSent();
179     try
180     {
181         rethrow_exception(ex);
182     }
183     catch(const std::exception& exc)
184     {
185         IncomingBase::exception(exc, true); // User thread
186     }
187     catch(...)
188     {
189         IncomingBase::exception("unknown c++ exception", true); // User thread
190     }
191 }
192 #endif
193 
194 void
checkResponseSent()195 IceInternal::IncomingAsync::checkResponseSent()
196 {
197     IceUtil::Mutex::Lock sync(*globalMutex);
198     if(_responseSent)
199     {
200         throw ResponseSentException(__FILE__, __LINE__);
201     }
202     _responseSent = true;
203 }
204 
205 #ifndef ICE_CPP11_MAPPING
AMD_Object_ice_invoke(Incoming & in)206 IceAsync::Ice::AMD_Object_ice_invoke::AMD_Object_ice_invoke(Incoming& in) : IncomingAsync(in)
207 {
208 }
209 
210 void
ice_response(bool ok,const vector<Byte> & outEncaps)211 IceAsync::Ice::AMD_Object_ice_invoke::ice_response(bool ok, const vector<Byte>& outEncaps)
212 {
213     if(outEncaps.empty())
214     {
215         writeParamEncaps(0, 0, ok);
216     }
217     else
218     {
219         writeParamEncaps(&outEncaps[0], static_cast<Int>(outEncaps.size()), ok);
220     }
221     completed();
222 }
223 
224 void
ice_response(bool ok,const pair<const Byte *,const Byte * > & outEncaps)225 IceAsync::Ice::AMD_Object_ice_invoke::ice_response(bool ok, const pair<const Byte*, const Byte*>& outEncaps)
226 {
227     writeParamEncaps(outEncaps.first, static_cast<Int>(outEncaps.second - outEncaps.first), ok);
228     completed();
229 }
230 #endif
231