|
1 // Copyright (c) 1997-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 // |
|
15 |
|
16 /** |
|
17 @file SS_SAP.CPP |
|
18 */ |
|
19 |
|
20 #define SYMBIAN_NETWORKING_UPS |
|
21 |
|
22 #include <ss_std.h> |
|
23 #include <ss_glob.h> |
|
24 #include <comms-infras/ss_roles.h> |
|
25 #include <comms-infras/ss_log.h> |
|
26 #include <comms-infras/ss_subconnflow.h> |
|
27 #include <ss_protprov.h> |
|
28 #include <comms-infras/es_sap.h> |
|
29 #include <ss_sock.h> |
|
30 #include <comms-infras/ss_nodemessages_dataclient.h> |
|
31 |
|
32 #include <elements/nm_signatures.h> |
|
33 |
|
34 |
|
35 #ifdef _DEBUG |
|
36 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
37 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
38 _LIT(KSpecAssert_ESockSSockss_sp, "ESockSSockss_sp."); |
|
39 #endif |
|
40 |
|
41 using namespace ESock; |
|
42 using namespace Messages; |
|
43 |
|
44 |
|
45 EXPORT_C CNetworkFlow::CNetworkFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf) |
|
46 : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf) |
|
47 { |
|
48 } |
|
49 |
|
50 EXPORT_C CNetworkFlow::~CNetworkFlow() |
|
51 { |
|
52 if (iLowerFlow) |
|
53 { |
|
54 iLowerFlow->Unbind(NULL,NULL); |
|
55 } |
|
56 } |
|
57 void |
|
58 CNetworkFlow::SetLocalName(TSockAddr& anAddr) |
|
59 /** Sets the local name (address) of the socket service provider entity. The format |
|
60 of the data in the TSockAddr object is defined by individual protocols. |
|
61 |
|
62 @param anAddr The address |
|
63 @return Returns KErrNone if the local name is correctly set or, if this is |
|
64 not the case, an informative error number. */ |
|
65 { |
|
66 iLocalAddressSet = ETrue; |
|
67 iLocalAddress = anAddr; |
|
68 |
|
69 } |
|
70 |
|
71 TInt CNetworkFlow::SetRemName(TSockAddr& anAddr) |
|
72 /** Sets the remote name (address) of the socket service provider entity. The format |
|
73 of the data in the TSockAddr object is defined by individual protocols. |
|
74 |
|
75 @param anAddr The address |
|
76 @return Returns KErrNone if the remote name is correctly set or, if this is |
|
77 not the case, an informative error number. */ |
|
78 { |
|
79 iRemoteAddressSet = ETrue; |
|
80 iRemoteAddress = anAddr; |
|
81 return KErrNone; |
|
82 } |
|
83 |
|
84 void CNetworkFlow::UpdateDestinationAddress(const TSockAddr& aDest) |
|
85 { |
|
86 iRemoteAddress = aDest; |
|
87 iRemoteAddressSet = ETrue; |
|
88 } |
|
89 |
|
90 TUint CNetworkFlow::Write(const TDesC8& /*aDesc*/, TUint /*aOptions*/, TSockAddr* anAddr) |
|
91 /** Sends data onto the network via the protocol. |
|
92 |
|
93 Connection-oriented sockets must be in a connected state (that is ConnectComplete() has |
|
94 been called on their MSocketNotify before Write() is called). |
|
95 |
|
96 The socket server keeps track of how much data is waiting and then tries to send it all |
|
97 until the protocol tells it to hold off by returning 0 (datagram sockets) or 'less than |
|
98 all data consumed' (stream sockets) to Write(). The protocol should call CanSend() when it |
|
99 is ready to send more data. |
|
100 |
|
101 anAddr is the address to write the data to. Connection oriented sockets always use the |
|
102 default value. |
|
103 |
|
104 @param aDesc The data to be sent. |
|
105 @param aOptions Protocol specific options. |
|
106 @param anAddr Address to write the data to. |
|
107 |
|
108 @returns For stream-oriented protocols the return value is the number of bytes actually written. |
|
109 If this is less than the length of the descriptor then the protocol should call CanSend() |
|
110 when it is ready to send more data. For datagram-oriented protocols, the write should return |
|
111 either 0 if the write cannot be completed, or the length of the descriptor if the write succeeds - |
|
112 no other values are valid. If the Write() must return 0, then it should call CanSend() when it is |
|
113 ready to send more data. If the Write() fails due to some error, then it should call Error() with |
|
114 an informative error number. |
|
115 */ |
|
116 { |
|
117 if (anAddr) |
|
118 { |
|
119 UpdateDestinationAddress(*anAddr); |
|
120 } |
|
121 return KErrNone; |
|
122 } |
|
123 |
|
124 TInt CNetworkFlow::Write(RMBufChain& /*aData*/, TUint /*aOptions*/, TSockAddr* anAddr) |
|
125 /** Sends data onto the network via the protocol. |
|
126 |
|
127 Connection-oriented sockets must be in a connected state (that is ConnectComplete() has |
|
128 been called on their MSocketNotify before Write() is called). |
|
129 |
|
130 The socket server keeps track of how much data is waiting and then tries to send it all |
|
131 until the protocol tells it to hold off by returning 0 (datagram sockets) or 'less than |
|
132 all data consumed' (stream sockets) to Write(). The protocol should call CanSend() when it |
|
133 is ready to send more data. |
|
134 |
|
135 anAddr is the address to write the data to. Connection oriented sockets always use the |
|
136 default value. |
|
137 |
|
138 @param aData The data to be sent. |
|
139 @param aOptions Protocol specific options. |
|
140 @param anAddr Address to write the data to. |
|
141 |
|
142 @returns For stream-oriented protocols the return value is the number of bytes actually written. |
|
143 If this is less than the length of the descriptor then the protocol should call CanSend() |
|
144 when it is ready to send more data. For datagram-oriented protocols, the write should return |
|
145 either 0 if the write cannot be completed, or the length of the descriptor if the write succeeds - |
|
146 no other values are valid. If the Write() must return 0, then it should call CanSend() when it is |
|
147 ready to send more data. If the Write() fails due to some error, then it should call Error() with |
|
148 an informative error number. |
|
149 */ |
|
150 { |
|
151 if (anAddr) |
|
152 { |
|
153 UpdateDestinationAddress(*anAddr); |
|
154 } |
|
155 return KErrNone; |
|
156 } |
|
157 |
|
158 |
|
159 |
|
160 void CNetworkFlow::BindToL(const TCFDataClient::TBindTo& aBindTo) |
|
161 /** |
|
162 Request from control side (at network layer) to indicate that the SubConnection is |
|
163 up and running and that we should bind to a Flow below. |
|
164 |
|
165 @param aLowerFlow Flow below to bind to. |
|
166 */ |
|
167 { |
|
168 LOG( ESockLog::Printf(_L("CNetworkFlow %08x:\tBindTo()"), this) ); |
|
169 |
|
170 const TNodeId& commsId = aBindTo.iNodeId; |
|
171 #if defined(__GCCXML__) |
|
172 CSubConnectionFlowBase* flow = reinterpret_cast<CSubConnectionFlowBase*>(reinterpret_cast<Messages::ANode*>(commsId.Ptr())); |
|
173 #else |
|
174 CSubConnectionFlowBase* flow = mcfnode_cast<CSubConnectionFlowBase>(reinterpret_cast<Messages::ANode*>(commsId.Ptr())); |
|
175 #endif |
|
176 |
|
177 if (flow==NULL) |
|
178 { |
|
179 __ASSERT_DEBUG(!commsId.IsNull(), User::Panic(KSpecAssert_ESockSSockss_sp, 1)); |
|
180 iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStopped(KErrDisconnected).CRef()); |
|
181 } |
|
182 |
|
183 //flows can only be directly bound when running in the same thread |
|
184 //Are we in the same thread? |
|
185 __ASSERT_DEBUG(commsId.Thread() == Id().Thread(), User::Panic(KSpecAssert_ESockSSockss_sp, 2)); |
|
186 |
|
187 if (iLowerFlow && iLowerFlow->Flow() != flow ) |
|
188 { |
|
189 //already bound -> unbind first. |
|
190 iLowerFlow->Unbind(NULL,NULL); |
|
191 iLowerFlow = NULL; |
|
192 iLowerControl = NULL; |
|
193 } |
|
194 |
|
195 if (iLowerFlow == NULL && flow != NULL) |
|
196 { |
|
197 iLowerFlow = flow->GetBinderControlL(); |
|
198 iLowerControl = iLowerFlow->GetControlL(KNullDesC8); |
|
199 iLowerFlow->BindL(KNullDesC8, NULL,NULL); |
|
200 } |
|
201 } |
|
202 |
|
203 MSessionControl* CNetworkFlow::GetControlL(TInt /*aSessionType*/,MSessionControlNotify& aSessionControlNotify) |
|
204 { |
|
205 __ASSERT_DEBUG(iSessionControlNotify == NULL, User::Panic(KSpecAssert_ESockSSockss_sp, 3)); |
|
206 iSessionControlNotify = &aSessionControlNotify; |
|
207 return this; |
|
208 } |
|
209 |
|
210 MSessionData* CNetworkFlow::BindL(MSessionDataNotify& aNotify) |
|
211 { |
|
212 __ASSERT_DEBUG(iSessionDataNotify == NULL, User::Panic(KSpecAssert_ESockSSockss_sp, 4)); |
|
213 iSessionDataNotify = &aNotify; |
|
214 iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef()); |
|
215 return this; |
|
216 } |
|
217 |
|
218 void CNetworkFlow::Unbind() |
|
219 { |
|
220 if (iSessionDataNotify) // if not already unbound |
|
221 { |
|
222 iSessionControlNotify = NULL; |
|
223 iSessionDataNotify = NULL; |
|
224 if(iSubConnectionProvider.IsOpen()) |
|
225 { |
|
226 if(iDCIdle < EIdle) |
|
227 { |
|
228 iDCIdle = EIdle; |
|
229 ProcessDCIdleState(); |
|
230 } |
|
231 } |
|
232 else |
|
233 { |
|
234 // Legacy flows lack a SCPR to look after their destruction so need to suicide |
|
235 delete this; |
|
236 } |
|
237 } |
|
238 } |
|
239 |
|
240 CSubConnectionFlowBase* CNetworkFlow::Flow() |
|
241 { |
|
242 return this; |
|
243 } |
|
244 |
|
245 MFlowBinderControl* CNetworkFlow::DoGetBinderControlL() |
|
246 { |
|
247 return this; |
|
248 } |
|
249 |
|
250 void CNetworkFlow::ProcessDCIdleState() |
|
251 { |
|
252 #ifdef SYMBIAN_NETWORKING_UPS |
|
253 if(iDCIdle == EIdle && !ActivityRunning()) |
|
254 #else |
|
255 if(iDCIdle == EIdle && !iNoBearerRunning) |
|
256 #endif |
|
257 { |
|
258 iDCIdle = EIdleSent; |
|
259 iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef()); |
|
260 } |
|
261 } |
|
262 |
|
263 |
|
264 |