|
1 // Copyright (c) 2004-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 // Accenture - modified for fshell's btincomingserial.dll |
|
13 // |
|
14 // Description: |
|
15 // Name : CBtService.cpp |
|
16 // Part of : ex_btsocket |
|
17 // Created : 17/11/2004 by Shane Kearns |
|
18 // Server "smart connector" class |
|
19 // Version : |
|
20 // |
|
21 // |
|
22 |
|
23 #include "btservice.h" |
|
24 #include "btdebug.h" |
|
25 #include "btincomingserial.h" |
|
26 |
|
27 /** |
|
28 Standard Symbian style 2 phase construction |
|
29 @param aServiceUUID a universally unique identifier for this application. |
|
30 @param aSdpSession a constructed sdp session owned by the application |
|
31 @param aSocketServer a constructed socket server session owned by the application |
|
32 @param aOwner the owning class which should receive notification of new connections |
|
33 @param aProtocol the protocol (RFCOMM or L2CAP) to register |
|
34 @param aSecurity optional security settings to use on the socket instead of system defaults |
|
35 */ |
|
36 CBtService* CBtService::NewL(const TUUID& aServiceUUID, |
|
37 RSdp& aSdpSession, |
|
38 RSocketServ& aSocketServer, |
|
39 CBluetoothIncomingSerialConnection& aOwner, |
|
40 TUint aProtocol, |
|
41 const TBTServiceSecurity* aSecurity) |
|
42 { |
|
43 TRACE1("+CBtService::NewL"); |
|
44 __ASSERT_ALWAYS(aProtocol == KL2CAP || aProtocol == KRFCOMM, PANIC()); |
|
45 CBtService* self = new(ELeave) CBtService(aSocketServer, aOwner, aProtocol); |
|
46 CleanupStack::PushL(self); |
|
47 self->ConstructL(aServiceUUID, aSdpSession, aSecurity); |
|
48 CleanupStack::Pop(self); |
|
49 TRACE1("-CBtService::NewL"); |
|
50 return self; |
|
51 } |
|
52 |
|
53 /** |
|
54 Standard 1st phase constructor, inialise member variables |
|
55 */ |
|
56 CBtService::CBtService(RSocketServ& aSocketServer, CBluetoothIncomingSerialConnection& aOwner, TUint aProtocol) : |
|
57 iSocketServer(aSocketServer), |
|
58 iOwner(aOwner), |
|
59 iProtocol(aProtocol) |
|
60 { |
|
61 TRACE2("CBtService::CBtService@%08x", this); |
|
62 } |
|
63 |
|
64 /** |
|
65 Standard 2nd phase constructor, perform initialisation which could leave |
|
66 */ |
|
67 void CBtService::ConstructL(const TUUID& aServiceUUID, RSdp& aSdpSession, const TBTServiceSecurity* aSecurity) |
|
68 { |
|
69 TRACE1("+CBtService::ConstructL"); |
|
70 |
|
71 //open handle so it is certain to be valid in the destructor |
|
72 User::LeaveIfError(iServiceRecord.Open(aSdpSession)); |
|
73 |
|
74 //First, create a listening socket |
|
75 if(iProtocol == KL2CAP) |
|
76 { |
|
77 iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockSeqPacket, KL2CAP); |
|
78 //bind the socket to a port |
|
79 TL2CAPSockAddr addr; |
|
80 addr.SetPort(KL2CAPPassiveAutoBind); //allow the stack to choose a free port automatically |
|
81 if(aSecurity) |
|
82 { |
|
83 addr.SetSecurity(*aSecurity); //set security requirements, if present |
|
84 } |
|
85 User::LeaveIfError(iAcceptorSocket->Bind(addr)); |
|
86 } |
|
87 else if(iProtocol == KRFCOMM) |
|
88 { |
|
89 iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockStream, KRFCOMM); |
|
90 //bind the socket to a port |
|
91 TRfcommSockAddr addr; |
|
92 addr.SetPort(KRfcommPassiveAutoBind); //allow the stack to choose a free port automatically |
|
93 if(aSecurity) |
|
94 { |
|
95 addr.SetSecurity(*aSecurity); //set security requirements, if present |
|
96 } |
|
97 User::LeaveIfError(iAcceptorSocket->Bind(addr)); |
|
98 } |
|
99 User::LeaveIfError(iAcceptorSocket->Listen(1)); |
|
100 |
|
101 //Now, register in the SDP database |
|
102 TUint port = iAcceptorSocket->LocalPort(); //get the port chosen by the stack |
|
103 TRACE2("Listening for connections on port %d", port); |
|
104 iServiceRecord.CreateServiceRecordL(aServiceUUID, iServiceRecordHandle); |
|
105 |
|
106 // Set attr 4 (protocol list) to L2CAP, and RFCOMM |
|
107 CSdpAttrValueDES *attrValDES; |
|
108 |
|
109 //This following code is doing these steps |
|
110 //1. create a DES (data element set) attribute |
|
111 //2. within that list, create a DES for each protocol, L2CAP and optionally RFCOMM |
|
112 //3. each protocol is a list of elements, the UUID of the protocol, and the port to connect to. |
|
113 //4. the service record is updated to include the new attribute |
|
114 //5. discard the attribute we built, as it has been copied to the SDP server |
|
115 attrValDES = CSdpAttrValueDES::NewDESL(NULL); |
|
116 CleanupStack::PushL(attrValDES); |
|
117 if(iProtocol == KL2CAP) |
|
118 { |
|
119 TRACE1("Registering SDP PDL for L2CAP"); |
|
120 //This code will register an L2CAP (datagram) service |
|
121 attrValDES |
|
122 ->StartListL() |
|
123 ->BuildDESL() |
|
124 ->StartListL() |
|
125 ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP |
|
126 ->BuildUintL(TSdpIntBuf<TUint16>(TUint16(port))) // The Protocol Service Multiplexor (port) for our service |
|
127 ->EndListL() |
|
128 ->EndListL(); |
|
129 } |
|
130 else if(iProtocol == KRFCOMM) |
|
131 { |
|
132 TRACE1("Registering SDP PDL for RFCOMM"); |
|
133 //This code will register an RFCOMM (stream) service |
|
134 attrValDES |
|
135 ->StartListL() |
|
136 ->BuildDESL() |
|
137 ->StartListL() |
|
138 ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP |
|
139 ->EndListL() |
|
140 ->BuildDESL() |
|
141 ->StartListL() |
|
142 ->BuildUUIDL(TUUID(TUint16(KRFCOMM))) // RFCOMM |
|
143 ->BuildUintL(TSdpIntBuf<TUint8>(TUint8(port))) |
|
144 ->EndListL() |
|
145 ->EndListL(); |
|
146 } |
|
147 iServiceRecord.UpdateAttributeL(iServiceRecordHandle, KSdpAttrIdProtocolDescriptorList, *attrValDES); |
|
148 CleanupStack::PopAndDestroy(attrValDES); |
|
149 attrValDES = NULL; |
|
150 |
|
151 _LIT8(KSerialPortServiceName, "Bluetooth Serial Console"); |
|
152 CSdpAttrValueString* attrVal = CSdpAttrValueString::NewStringL(KSerialPortServiceName); |
|
153 CleanupStack::PushL(attrVal); |
|
154 iServiceRecord.UpdateAttributeL(iServiceRecordHandle, |
|
155 KSdpAttrIdBasePrimaryLanguage + KSdpAttrIdOffsetServiceName, *attrVal); |
|
156 CleanupStack::PopAndDestroy(attrVal); |
|
157 attrVal = NULL; |
|
158 TRACE1("-CBtService::ConstructL"); |
|
159 } |
|
160 |
|
161 CBtService::~CBtService() |
|
162 { |
|
163 TRACE1("CBtService::~CBtService"); |
|
164 //attempt to remove the SDP record |
|
165 TRAP_IGNORE(iServiceRecord.DeleteRecordL(iServiceRecordHandle)); |
|
166 iServiceRecord.Close(); |
|
167 delete iAcceptorSocket; |
|
168 } |
|
169 |
|
170 /** |
|
171 Accept a new connection. |
|
172 When the incoming connection has been made, HandleAcceptCompleteL() will be called |
|
173 in this class. |
|
174 That function informs the owner by calling HandleNewConnection() or HandleConnectFailed() |
|
175 @param aBlankSocket an empty socket to receive the incoming connection. |
|
176 */ |
|
177 void CBtService::AcceptConnection(CBluetoothSocket& aBlankSocket) |
|
178 { |
|
179 TRACE1("+CBtService::AcceptConnection"); |
|
180 __ASSERT_ALWAYS(iConnectionSocket == NULL, PANIC()); |
|
181 iConnectionSocket = &aBlankSocket; |
|
182 iAcceptorSocket->Accept(*iConnectionSocket); |
|
183 TRACE1("-CBtService::AcceptConnection"); |
|
184 } |
|
185 |
|
186 /** |
|
187 Callback from CBluetoothSocket when a new incoming connection is complete. |
|
188 Inform the owner |
|
189 */ |
|
190 void CBtService::HandleAcceptCompleteL(TInt aErr) |
|
191 { |
|
192 TRACE1("+CBtService::HandleAcceptCompleteL"); |
|
193 if(aErr == KErrNone) |
|
194 { |
|
195 iOwner.HandleNewConnection(iConnectionSocket); |
|
196 } |
|
197 else |
|
198 { |
|
199 iOwner.HandleConnectFailed(aErr); |
|
200 } |
|
201 iConnectionSocket = NULL; |
|
202 TRACE1("-CBtService::HandleAcceptCompleteL"); |
|
203 } |
|
204 |
|
205 /** |
|
206 This function is not used but must be implemented as it is pure virtual |
|
207 */ |
|
208 void CBtService::HandleConnectCompleteL(TInt /*aErr*/) |
|
209 { |
|
210 TRACE1("+CBtService::HandleConnectCompleteL"); |
|
211 PANIC(); |
|
212 } |
|
213 |
|
214 /** |
|
215 This function is not used but must be implemented as it is pure virtual |
|
216 */ |
|
217 void CBtService::HandleShutdownCompleteL(TInt /*aErr*/) |
|
218 { |
|
219 TRACE1("+CBtService::HandleShutdownCompleteL"); |
|
220 PANIC(); |
|
221 } |
|
222 |
|
223 /** |
|
224 This function is not used but must be implemented as it is pure virtual |
|
225 */ |
|
226 void CBtService::HandleSendCompleteL(TInt /*aErr*/) |
|
227 { |
|
228 TRACE1("+CBtService::HandleSendCompleteL"); |
|
229 PANIC(); |
|
230 } |
|
231 |
|
232 /** |
|
233 This function is not used but must be implemented as it is pure virtual |
|
234 */ |
|
235 void CBtService::HandleReceiveCompleteL(TInt /*aErr*/) |
|
236 { |
|
237 TRACE1("+CBtService::HandleReceiveCompleteL"); |
|
238 PANIC(); |
|
239 } |
|
240 |
|
241 /** |
|
242 This function is not used but must be implemented as it is pure virtual |
|
243 */ |
|
244 void CBtService::HandleIoctlCompleteL(TInt /*aErr*/) |
|
245 { |
|
246 TRACE1("+CBtService::HandleIoctlCompleteL"); |
|
247 PANIC(); |
|
248 } |
|
249 |
|
250 /** |
|
251 This function is not used but must be implemented as it is pure virtual |
|
252 */ |
|
253 void CBtService::HandleActivateBasebandEventNotifierCompleteL(TInt /*aErr*/, TBTBasebandEventNotification& /*aEventNotification*/) |
|
254 { |
|
255 TRACE1("+CBtService::HandleActivateBasebandEventNotifierCompleteL"); |
|
256 PANIC(); |
|
257 } |
|
258 |