|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // SIP SubConnection Provider states/transitions |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 #include "sipdeftscpr.h" |
|
24 #include "sipscpr.h" |
|
25 #include "sipscprstates.h" |
|
26 |
|
27 |
|
28 |
|
29 using namespace ESock; |
|
30 using namespace NetStateMachine; |
|
31 using namespace SipSCpr; |
|
32 using namespace SipSCprStates; |
|
33 |
|
34 |
|
35 //=========================================== |
|
36 // |
|
37 // SIP Sub Connection Provider States |
|
38 // |
|
39 //=========================================== |
|
40 namespace SipSCprStates |
|
41 { |
|
42 |
|
43 //=================================================================================== |
|
44 // |
|
45 // StartConnection Activity |
|
46 // |
|
47 //==================================================================================== |
|
48 |
|
49 DEFINE_SMELEMENT(TNoTagOrAlreadyStarted,NetStateMachine::MStateFork, SipSCprStates::TContext) |
|
50 DEFINE_SMELEMENT(TStartSession, NetStateMachine::MStateTransition, SipSCprStates::TContext) |
|
51 DEFINE_SMELEMENT(TAwaitingSessionEstablished,NetStateMachine::MState, SipSCprStates::TContext) |
|
52 |
|
53 |
|
54 TInt TNoTagOrAlreadyStarted::TransitionTag() |
|
55 { |
|
56 if(iContext.Node().iStage == SipSCpr::EActive) |
|
57 { |
|
58 return CoreNetStates::KAlreadyStarted; |
|
59 } |
|
60 return MeshMachine::KNoTag; |
|
61 } |
|
62 |
|
63 void TStartSession::DoL() |
|
64 { |
|
65 //check error conditions before starting sip session |
|
66 TInt stage = iContext.Node().iStage; |
|
67 const Messages::TNodeId& self = iContext.Node().NodeId(); |
|
68 if(stage != SipSCpr::EFresh) |
|
69 { |
|
70 switch(stage) |
|
71 { |
|
72 case SipSCpr::EStopped: |
|
73 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start stopped subconnection"))); |
|
74 |
|
75 Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStart,self),TSipSCprMessages::TSipSessionEstablished(KErrAbort).CRef()); |
|
76 break; |
|
77 case SipSCpr::EStopping: |
|
78 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start stopping subconnection"))); |
|
79 Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStart,self),TSipSCprMessages::TSipSessionEstablished(KErrAbort).CRef()); |
|
80 break; |
|
81 } |
|
82 } |
|
83 |
|
84 //In the case of SIP SubConnection, the session params should be be set before we start a call. |
|
85 TSipParams& sipParams = iContext.Node().iSipSm->GetSipParams(); |
|
86 // Check should be made only to non-incoming request. For incoming request the |
|
87 // sipParams won't be set in SIP SCPR. The incoming params will be saved in iParameterBundle |
|
88 TInt err; |
|
89 if(!(iContext.Node().iAwaitingSubConnection) && sipParams.iRequest == TSipHLConsts::ERequestNone) |
|
90 { |
|
91 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start SIP subconnection if Params are notset"))); |
|
92 err = KErrNotSupported; |
|
93 } |
|
94 else |
|
95 { |
|
96 if (iContext.Node().subconType == RSubConnection::EWaitIncoming) |
|
97 { |
|
98 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("appears to be an incoming call subconection, accepting"))); |
|
99 err = iContext.Node().iSipSm->AcceptCall(); |
|
100 } |
|
101 else |
|
102 { |
|
103 err = iContext.Node().iSipSm->StartCall(); |
|
104 } |
|
105 } |
|
106 |
|
107 if (KErrNone != err) |
|
108 { |
|
109 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start SIP subconnection if Params are notset"))); |
|
110 Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStart,self),TSipSCprMessages::TSipSessionEstablished(err).CRef()); |
|
111 } |
|
112 //Expect Response |
|
113 iContext.Node().iActivityAwaitingResponse = iContext.iNodeActivity->ActivityId(); |
|
114 iContext.iNodeActivity->SetPostedTo(iContext.Node().NodeId()); |
|
115 iContext.Node().iStage = SipSCpr::EStarting; |
|
116 } |
|
117 |
|
118 TBool TAwaitingSessionEstablished::Accept() |
|
119 { |
|
120 if(iContext.iMessage.IsMessage<TSipSCprMessages::TSipSessionEstablished>()) |
|
121 { |
|
122 TSipSCprMessages::TSipSessionEstablished* msg = Messages::message_cast<TSipSCprMessages::TSipSessionEstablished>(&iContext.iMessage); |
|
123 if (msg->iValue == KErrNone) |
|
124 { |
|
125 // This means we have a successful session |
|
126 iContext.Node().iStage = SipSCpr::EActive; |
|
127 return ETrue; |
|
128 } |
|
129 else |
|
130 { |
|
131 //session start failed |
|
132 //Set the error for activity and will be cleared using TClearError |
|
133 TInt error = msg->iValue; |
|
134 iContext.iNodeActivity->SetError(error); |
|
135 return ETrue; |
|
136 } |
|
137 } |
|
138 |
|
139 return EFalse; |
|
140 } |
|
141 |
|
142 //======================================================================================================== |
|
143 // |
|
144 // Stop Activiity |
|
145 // |
|
146 //======================================================================================================== |
|
147 |
|
148 DEFINE_SMELEMENT(TNoTagOrAlreadyStopped, NetStateMachine::MStateFork, SipSCprStates::TContext) |
|
149 DEFINE_SMELEMENT(TStopSession, NetStateMachine::MStateTransition, SipSCprStates::TContext) |
|
150 DEFINE_SMELEMENT(TAwaitingSessionTerminated,NetStateMachine::MState, SipSCprStates::TContext) |
|
151 |
|
152 |
|
153 TInt TNoTagOrAlreadyStopped::TransitionTag() |
|
154 { |
|
155 |
|
156 //iStage defined only for non-deft SCPR |
|
157 TInt stage = iContext.Node().iStage; |
|
158 if (iContext.Node().iStage && iContext.Node().iStage >= SipSCpr::EStopping) |
|
159 { |
|
160 return CoreNetStates::KAlreadyStopped; |
|
161 } |
|
162 return MeshMachine::KNoTag; |
|
163 } |
|
164 |
|
165 void TStopSession::DoL() |
|
166 { |
|
167 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("AStopSession::DoL"))); |
|
168 |
|
169 //there's no need to check message type before casting as it should've been checked |
|
170 //by the State::Accept() => cast & assert if not the desired type |
|
171 iContext.Node().iStopCode = Messages::message_cast<TCFServiceProvider::TStop>(iContext.iMessage).iValue; |
|
172 TInt err; |
|
173 |
|
174 if (iContext.Node().iStage == SipSCpr::EFresh) |
|
175 { |
|
176 err = KErrNotReady; |
|
177 } |
|
178 //If this is an incoming call that hasn't been accepted yet. We should |
|
179 //reject it. Otherwise we should just stop it. |
|
180 else if (iContext.Node().iAwaitingSubConnection && iContext.Node().iStage == SipSCpr::EStarting) |
|
181 { |
|
182 err = iContext.Node().iSipSm->RejectCall(); |
|
183 } |
|
184 else |
|
185 { |
|
186 err = iContext.Node().iSipSm->StopCall(); |
|
187 } |
|
188 |
|
189 if (KErrNone != err) |
|
190 { |
|
191 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot stop SIP subconnection if Params are notset"))); |
|
192 const Messages::TNodeId& self = iContext.Node().NodeId(); |
|
193 Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStop,self),TSipSCprMessages::TSipSessionTerminated(err).CRef()); |
|
194 } |
|
195 |
|
196 iContext.Node().iActivityAwaitingResponse = iContext.iNodeActivity->ActivityId(); |
|
197 iContext.iNodeActivity->SetPostedTo(iContext.Node().NodeId()); |
|
198 iContext.Node().iStage = SipSCpr::EStopping; |
|
199 } |
|
200 |
|
201 TBool TAwaitingSessionTerminated::Accept() |
|
202 { |
|
203 if(iContext.iMessage.IsMessage<TSipSCprMessages::TSipSessionTerminated>()) |
|
204 { |
|
205 TSipSCprMessages::TSipSessionTerminated* msg = Messages::message_cast<TSipSCprMessages::TSipSessionTerminated>(&iContext.iMessage); |
|
206 if (msg->iValue == KErrNone) |
|
207 { |
|
208 iContext.Node().iStage = SipSCpr::EStopped; |
|
209 return ETrue; |
|
210 } |
|
211 else |
|
212 { |
|
213 //Set the error for activity and will be cleared using TClearError |
|
214 TInt error = msg->iValue; |
|
215 iContext.iNodeActivity->SetError(error); |
|
216 return ETrue; |
|
217 } |
|
218 } |
|
219 return EFalse; |
|
220 } |
|
221 |
|
222 |
|
223 //================================================================================================= |
|
224 // |
|
225 //Set Params |
|
226 // |
|
227 //================================================================================================== |
|
228 |
|
229 DEFINE_SMELEMENT(TSetParameters,NetStateMachine::MStateTransition, SipSCprStates::TContext) |
|
230 void TSetParameters::DoL() |
|
231 { |
|
232 TRAPD(err, iContext.Node().DoParametersAboutToBeSetL(iContext.Node().iParameterBundle)); |
|
233 if(KErrNone != err) |
|
234 { |
|
235 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("call to DoParemetersAboutToBeSet failed in ASetParameters::DoL() [error=%d]"), err)); |
|
236 User::Leave(err); |
|
237 } |
|
238 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
239 iContext.PostToSender(TCFScpr::TSetParamsResponse(iContext.Node().iParameterBundle).CRef()); |
|
240 #else |
|
241 iContext.PostToSender(TCFScpr::TParamsResponse(iContext.Node().iParameterBundle).CRef()); |
|
242 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
243 } |
|
244 |
|
245 |
|
246 |
|
247 DEFINE_SMELEMENT(TStoreProvision, NetStateMachine::MStateTransition, SipSCprStates::TContext) |
|
248 void TStoreProvision::DoL() |
|
249 { |
|
250 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("AStoreProvision::DoL()"))); |
|
251 PRStates::TStoreProvision storeProvision(iContext); |
|
252 storeProvision.DoL(); |
|
253 |
|
254 const TSipCprProvisionInfo* ext = static_cast<const TSipCprProvisionInfo*>(iContext.Node().AccessPointConfig().FindExtension(STypeId::CreateSTypeId(TSipCprProvisionInfo::EUid, TSipCprProvisionInfo::ETypeId))); |
|
255 if (ext) |
|
256 { |
|
257 iContext.Node().iTransitionEngine = ext->iTransitionEngine; |
|
258 iContext.Node().iFromField = ext->iFromField; |
|
259 |
|
260 // Set the falg for WaitForIncoming connection |
|
261 if (iContext.Node().iAwaitingSubConnection) |
|
262 { |
|
263 iContext.Node().iActivityAwaitingResponse = iContext.ActivityId(); |
|
264 } |
|
265 // Create the SIP state machine |
|
266 iContext.Node().CreateStateMachineL(); |
|
267 __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::TStoreProvision() [this=%08x]\t -- SIP State Machine created "), this)); |
|
268 |
|
269 } |
|
270 } |
|
271 }//namespace SipSCprStates |
|
272 |