49 void TModeSpecificFecOptionHandlerBase::BuildNegativeResponse(TRetransmissionAndFlowControlOption& /*aPreferred*/, |
49 void TModeSpecificFecOptionHandlerBase::BuildNegativeResponse(TRetransmissionAndFlowControlOption& /*aPreferred*/, |
50 const TRetransmissionAndFlowControlOption& /*aPeer*/) const |
50 const TRetransmissionAndFlowControlOption& /*aPeer*/) const |
51 { |
51 { |
52 LOG_FUNC |
52 LOG_FUNC |
53 // Just send what we've got in Preferred. |
53 // Just send what we've got in Preferred. |
|
54 } |
|
55 |
|
56 void TModeSpecificFecOptionHandlerBase::BuildRequestBasedOnUnacceptableParamsResponse( |
|
57 TRetransmissionAndFlowControlOption& aPreferred, |
|
58 const TRetransmissionAndFlowControlOption& aPeer, |
|
59 const TL2CapFecNegotiator& aFecNegotiator) const |
|
60 { |
|
61 LOG_FUNC |
|
62 // In general the only negotiable parameter is channel mode - that's what we should |
|
63 // take from the suggested response passed here in aPeer. The rest of the parameters are |
|
64 // informative and we should use our own values, based on the mode - the remote can not |
|
65 // reject informative parameters. |
|
66 // Note on interop: |
|
67 // Unfortunately <= 9.4 Symbian code _WILL_ reject if e.g. we send a MaxTransmit value |
|
68 // which is greater than its own preference. To interoperate with those this method is |
|
69 // overridden in the Legacy handler. |
|
70 |
|
71 aPreferred = TRetransmissionAndFlowControlOption(aPeer.LinkMode(), ETrue); |
|
72 SetMaxTransmit(aPreferred, aFecNegotiator.MaxTransmit()); |
|
73 ZeroUnspecifiedRequestFields(aPreferred); |
54 } |
74 } |
55 |
75 |
56 void TModeSpecificFecOptionHandlerBase::SetMaxTransmit(TRetransmissionAndFlowControlOption& aFecOption, TUint8 /*aMaxTransmit*/) const |
76 void TModeSpecificFecOptionHandlerBase::SetMaxTransmit(TRetransmissionAndFlowControlOption& aFecOption, TUint8 /*aMaxTransmit*/) const |
57 { |
77 { |
58 LOG_FUNC |
78 LOG_FUNC |
247 { |
267 { |
248 aFecOption.SetMaxTransmit(aMaxTransmit == TRetransmissionAndFlowControlOption::KMaxValidEnhancedNumberTransmit ? |
268 aFecOption.SetMaxTransmit(aMaxTransmit == TRetransmissionAndFlowControlOption::KMaxValidEnhancedNumberTransmit ? |
249 TRetransmissionAndFlowControlOption::KMaxValidLegacyNumberTransmit : |
269 TRetransmissionAndFlowControlOption::KMaxValidLegacyNumberTransmit : |
250 aMaxTransmit); |
270 aMaxTransmit); |
251 } |
271 } |
|
272 |
|
273 void TLegacyFecHandler::BuildRequestBasedOnUnacceptableParamsResponse( |
|
274 TRetransmissionAndFlowControlOption& aPreferred, |
|
275 const TRetransmissionAndFlowControlOption& aPeer, |
|
276 const TL2CapFecNegotiator& aFecNegotiator) const |
|
277 { |
|
278 LOG_FUNC |
|
279 // In general the only negotiable parameter is channel mode - that's what we should |
|
280 // take from the suggested response passed here in aPeer. The rest of the parameters are |
|
281 // informative and we should use our own values, based on the mode - the remote can not |
|
282 // reject informative parameters. |
|
283 // |
|
284 // HOWEVER: |
|
285 // |
|
286 // Unfortunately <= 9.4 Symbian code _WILL_ reject if e.g. we send a MaxTransmit value |
|
287 // which is greater than its own preference. To interoperate with those we take |
|
288 // the whole FEC option suggested by the remote, including the informational parameters. |
|
289 // <= 9.4 Symbian devices implement RTM and FC modes (and not ERTM and Streaming). |
|
290 // Additionally, pretty much noone else in the market does - most people jumped from |
|
291 // Basic straight to ERTM & Streaming. So it can be assumed that: |
|
292 // Legacy (RTM & FC) ~= pre-ERTM Symbian. |
|
293 |
|
294 typedef TRetransmissionAndFlowControlOption TFec; // just 'coz I'm lazy |
|
295 |
|
296 // Use the remote's whole suggestion if all informational parameters look edible ... |
|
297 if (aPeer.TxWindowSize() >= TFec::KMinValidTxWindowSize && |
|
298 aPeer.MaxTransmit() >= TFec::KMinValidNumberTransmit && |
|
299 aPeer.RetransmissionTimeout() >= TFec::KMinAcceptableRetransmissionTimeout && |
|
300 aPeer.MonitorTimeout() >= TFec::KMinAcceptableMonitorTimeout && |
|
301 aPeer.MaximumPDUSize() >= TFec::KMinValidMaximumPDUSize) |
|
302 { |
|
303 aPreferred = aPeer; |
|
304 } |
|
305 else // ... otherwise only use channel mode to prevent DoS attacks. |
|
306 { |
|
307 aPreferred = TRetransmissionAndFlowControlOption(aPeer.LinkMode(), ETrue); |
|
308 SetMaxTransmit(aPreferred, aFecNegotiator.MaxTransmit()); |
|
309 ZeroUnspecifiedRequestFields(aPreferred); |
|
310 } |
|
311 } |
|
312 |
252 |
313 |
253 // Basic mode |
314 // Basic mode |
254 |
315 |
255 TBool TBasicFecHandler::IsOptionValid(const TRetransmissionAndFlowControlOption& /*aFecOption*/) const |
316 TBool TBasicFecHandler::IsOptionValid(const TRetransmissionAndFlowControlOption& /*aFecOption*/) const |
256 { |
317 { |
474 else |
535 else |
475 { |
536 { |
476 if (aIsUnacceptableParameters) |
537 if (aIsUnacceptableParameters) |
477 { |
538 { |
478 iConfigStatus = EOptionConfigOutstanding; |
539 iConfigStatus = EOptionConfigOutstanding; |
479 // Only take the channel mode from peer's proposal and set informational |
540 // Build a new request based on suggestion sent by the peer. |
480 // (i.e. all other) parameters to our values. |
541 iFecNegotiator.ModeSpecificHandlers().BuildRequestBasedOnUnacceptableParamsResponse( |
481 BuildRequest(aFecOption.LinkMode(), iPreferred); |
542 iPreferred, iPeer, iFecNegotiator); |
482 } |
543 } |
483 else |
544 else |
484 { |
545 { |
485 iConfigStatus = EOptionConfigComplete; |
546 iConfigStatus = EOptionConfigComplete; |
486 } |
547 } |