diff options
Diffstat (limited to 'linden/indra/newview/lleventpoll.cpp')
-rw-r--r-- | linden/indra/newview/lleventpoll.cpp | 99 |
1 files changed, 91 insertions, 8 deletions
diff --git a/linden/indra/newview/lleventpoll.cpp b/linden/indra/newview/lleventpoll.cpp index f00c05b..083c46c 100644 --- a/linden/indra/newview/lleventpoll.cpp +++ b/linden/indra/newview/lleventpoll.cpp | |||
@@ -31,16 +31,26 @@ | |||
31 | 31 | ||
32 | #include "llviewerprecompiledheaders.h" | 32 | #include "llviewerprecompiledheaders.h" |
33 | 33 | ||
34 | #include "llappviewer.h" | ||
34 | #include "llagent.h" | 35 | #include "llagent.h" |
35 | #include "lleventpoll.h" | 36 | #include "lleventpoll.h" |
36 | 37 | ||
37 | #include "llhttpclient.h" | 38 | #include "llhttpclient.h" |
39 | #include "llhttpstatuscodes.h" | ||
38 | #include "llsdserialize.h" | 40 | #include "llsdserialize.h" |
41 | #include "lltimer.h" | ||
39 | #include "llviewerregion.h" | 42 | #include "llviewerregion.h" |
40 | #include "message.h" | 43 | #include "message.h" |
41 | 44 | ||
42 | namespace | 45 | namespace |
43 | { | 46 | { |
47 | // We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error. | ||
48 | // This means we attempt to recover relatively quickly but back off giving more time to recover | ||
49 | // until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts. | ||
50 | const F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout. | ||
51 | const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout. | ||
52 | const S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules. | ||
53 | |||
44 | class LLEventPollResponder : public LLHTTPClient::Responder | 54 | class LLEventPollResponder : public LLHTTPClient::Responder |
45 | { | 55 | { |
46 | public: | 56 | public: |
@@ -48,15 +58,21 @@ namespace | |||
48 | static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender); | 58 | static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender); |
49 | void stop(); | 59 | void stop(); |
50 | 60 | ||
61 | void makeRequest(); | ||
62 | |||
51 | private: | 63 | private: |
52 | LLEventPollResponder(const std::string& pollURL, const LLHost& sender); | 64 | LLEventPollResponder(const std::string& pollURL, const LLHost& sender); |
53 | ~LLEventPollResponder(); | 65 | ~LLEventPollResponder(); |
54 | 66 | ||
55 | void makeRequest(); | 67 | |
56 | void handleMessage(const LLSD& content); | 68 | void handleMessage(const LLSD& content); |
57 | virtual void error(U32 status, const std::string& reason); | 69 | virtual void error(U32 status, const std::string& reason); |
58 | virtual void result(const LLSD& content); | 70 | virtual void result(const LLSD& content); |
59 | 71 | ||
72 | virtual void completedRaw(U32 status, | ||
73 | const std::string& reason, | ||
74 | const LLChannelDescriptors& channels, | ||
75 | const LLIOPipe::buffer_ptr_t& buffer); | ||
60 | private: | 76 | private: |
61 | 77 | ||
62 | bool mDone; | 78 | bool mDone; |
@@ -69,6 +85,27 @@ namespace | |||
69 | // these are only here for debugging so we can see which poller is which | 85 | // these are only here for debugging so we can see which poller is which |
70 | static int sCount; | 86 | static int sCount; |
71 | int mCount; | 87 | int mCount; |
88 | S32 mErrorCount; | ||
89 | }; | ||
90 | |||
91 | class LLEventPollEventTimer : public LLEventTimer | ||
92 | { | ||
93 | typedef boost::intrusive_ptr<LLEventPollResponder> EventPollResponderPtr; | ||
94 | |||
95 | public: | ||
96 | LLEventPollEventTimer(F32 period, EventPollResponderPtr responder) | ||
97 | : LLEventTimer(period), mResponder(responder) | ||
98 | { } | ||
99 | |||
100 | virtual BOOL tick() | ||
101 | { | ||
102 | mResponder->makeRequest(); | ||
103 | return TRUE; // Causes this instance to be deleted. | ||
104 | } | ||
105 | |||
106 | private: | ||
107 | |||
108 | EventPollResponderPtr mResponder; | ||
72 | }; | 109 | }; |
73 | 110 | ||
74 | //static | 111 | //static |
@@ -94,7 +131,8 @@ namespace | |||
94 | LLEventPollResponder::LLEventPollResponder(const std::string& pollURL, const LLHost& sender) | 131 | LLEventPollResponder::LLEventPollResponder(const std::string& pollURL, const LLHost& sender) |
95 | : mDone(false), | 132 | : mDone(false), |
96 | mPollURL(pollURL), | 133 | mPollURL(pollURL), |
97 | mCount(++sCount) | 134 | mCount(++sCount), |
135 | mErrorCount(0) | ||
98 | { | 136 | { |
99 | //extract host and port of simulator to set as sender | 137 | //extract host and port of simulator to set as sender |
100 | LLViewerRegion *regionp = gAgent.getRegion(); | 138 | LLViewerRegion *regionp = gAgent.getRegion(); |
@@ -114,6 +152,24 @@ namespace | |||
114 | << mPollURL << llendl; | 152 | << mPollURL << llendl; |
115 | } | 153 | } |
116 | 154 | ||
155 | // virtual | ||
156 | void LLEventPollResponder::completedRaw(U32 status, | ||
157 | const std::string& reason, | ||
158 | const LLChannelDescriptors& channels, | ||
159 | const LLIOPipe::buffer_ptr_t& buffer) | ||
160 | { | ||
161 | if (status == HTTP_BAD_GATEWAY) | ||
162 | { | ||
163 | // These errors are not parsable as LLSD, | ||
164 | // which LLHTTPClient::Responder::completedRaw will try to do. | ||
165 | completed(status, reason, LLSD()); | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | LLHTTPClient::Responder::completedRaw(status,reason,channels,buffer); | ||
170 | } | ||
171 | } | ||
172 | |||
117 | void LLEventPollResponder::makeRequest() | 173 | void LLEventPollResponder::makeRequest() |
118 | { | 174 | { |
119 | LLSD request; | 175 | LLSD request; |
@@ -139,16 +195,37 @@ namespace | |||
139 | { | 195 | { |
140 | if (mDone) return; | 196 | if (mDone) return; |
141 | 197 | ||
142 | if(status != 499) | 198 | // A HTTP_BAD_GATEWAY (502) error is our standard timeout response |
199 | // we get this when there are no events. | ||
200 | if ( status == HTTP_BAD_GATEWAY ) | ||
201 | { | ||
202 | mErrorCount = 0; | ||
203 | makeRequest(); | ||
204 | } | ||
205 | else if (mErrorCount < MAX_EVENT_POLL_HTTP_ERRORS) | ||
206 | { | ||
207 | ++mErrorCount; | ||
208 | |||
209 | // The 'tick' will return TRUE causing the timer to delete this. | ||
210 | new LLEventPollEventTimer(EVENT_POLL_ERROR_RETRY_SECONDS | ||
211 | + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC | ||
212 | , this); | ||
213 | |||
214 | llwarns << "Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; | ||
215 | } | ||
216 | else | ||
143 | { | 217 | { |
144 | llwarns << "LLEventPollResponder::error: <" << mCount << "> got " | 218 | llwarns << "LLEventPollResponder::error: <" << mCount << "> got " |
145 | << status << ": " << reason | 219 | << status << ": " << reason |
146 | << (mDone ? " -- done" : "") << llendl; | 220 | << (mDone ? " -- done" : "") << llendl; |
147 | stop(); | 221 | stop(); |
148 | return; | ||
149 | } | ||
150 | 222 | ||
151 | makeRequest(); | 223 | // At this point we have given up and the viewer will not receive HTTP messages from the simulator. |
224 | // IMs, teleports, about land, selecing land, region crossing and more will all fail. | ||
225 | // They are essentially disconnected from the region even though some things may still work. | ||
226 | // Since things won't get better until they relog we force a disconnect now. | ||
227 | LLAppViewer::instance()->forceDisconnect("You have been disconnected from the region you were in."); | ||
228 | } | ||
152 | } | 229 | } |
153 | 230 | ||
154 | //virtual | 231 | //virtual |
@@ -159,10 +236,13 @@ namespace | |||
159 | 236 | ||
160 | if (mDone) return; | 237 | if (mDone) return; |
161 | 238 | ||
239 | mErrorCount = 0; | ||
240 | |||
162 | if (!content.get("events") || | 241 | if (!content.get("events") || |
163 | !content.get("id")) | 242 | !content.get("id")) |
164 | { | 243 | { |
165 | llwarns << "received event poll with no events or id key" << llendl; | 244 | llwarns << "received event poll with no events or id key" << llendl; |
245 | makeRequest(); | ||
166 | return; | 246 | return; |
167 | } | 247 | } |
168 | 248 | ||
@@ -192,10 +272,13 @@ namespace | |||
192 | } | 272 | } |
193 | } | 273 | } |
194 | 274 | ||
195 | LLEventPoll::LLEventPoll(const std::string& pollURL, const LLHost& sender) | 275 | LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender) |
196 | : mImpl(LLEventPollResponder::start(pollURL, sender)) | 276 | : mImpl(LLEventPollResponder::start(poll_url, sender)) |
197 | { } | 277 | { } |
198 | 278 | ||
199 | LLEventPoll::~LLEventPoll() | 279 | LLEventPoll::~LLEventPoll() |
200 | { | 280 | { |
281 | LLHTTPClient::Responder* responderp = mImpl.get(); | ||
282 | LLEventPollResponder* event_poll_responder = dynamic_cast<LLEventPollResponder*>(responderp); | ||
283 | if (event_poll_responder) event_poll_responder->stop(); | ||
201 | } | 284 | } |