|
1 /* |
|
2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Receives incoming DHCPInform messages |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <e32std.h> |
|
20 #include <es_sock.h> |
|
21 #include "dhcpconstants.h" |
|
22 #include "dhcppsylogging.h" |
|
23 #include "dhcpsocketlistener.h" |
|
24 |
|
25 const TInt KDhcpSizeOfMinXIDPacket = 0x08; |
|
26 const TInt KDhcpLocationOfXIDField = 0x04; |
|
27 const TInt KDhcpLengthOfXIDField = 0x04; |
|
28 const TInt KDhcpPeriodicTimerIntervalOneAndHalfSec(1500000); |
|
29 |
|
30 // ======== MEMBER FUNCTIONS ======== |
|
31 |
|
32 |
|
33 // --------------------------------------------------------------------------- |
|
34 // NewL |
|
35 // --------------------------------------------------------------------------- |
|
36 // |
|
37 CDhcpPsySocketListener* CDhcpPsySocketListener::NewL(RSocket* aSocket) |
|
38 { |
|
39 TRACESTRING ( "CDhcpPsySocketListener::NewL" ); |
|
40 CDhcpPsySocketListener* self = new( ELeave ) CDhcpPsySocketListener(aSocket); |
|
41 CleanupStack::PushL(self); |
|
42 self->ConstructL(); |
|
43 CleanupStack::Pop(); |
|
44 return self; |
|
45 } |
|
46 |
|
47 // --------------------------------------------------------------------------- |
|
48 // Destructor |
|
49 // --------------------------------------------------------------------------- |
|
50 // |
|
51 CDhcpPsySocketListener::~CDhcpPsySocketListener() |
|
52 { |
|
53 TRACESTRING( "CDhcpPsySocketListener::~CDhcpPsySocketListener" ); |
|
54 Cancel(); |
|
55 delete iRcvdDataHeapBufferPtr; |
|
56 delete iPeriodicTimer; |
|
57 } |
|
58 |
|
59 // --------------------------------------------------------------------------- |
|
60 // Constructor |
|
61 // --------------------------------------------------------------------------- |
|
62 // |
|
63 CDhcpPsySocketListener::CDhcpPsySocketListener( RSocket* aSocket) : |
|
64 CActive ( EPriorityStandard ), iSocket (aSocket), iRcvdDataBuffer ( 0, 0, KDhcpPacketLength ) |
|
65 { |
|
66 TRACESTRING( "CDhcpPsySocketListener::CDhcpPsySocketListener" ); |
|
67 CActiveScheduler::Add( this ); |
|
68 iAckPckg = TDhcpDataResponsePacket (); |
|
69 } |
|
70 |
|
71 // --------------------------------------------------------------------------- |
|
72 // CDhcpPsySocketListener::RcvDHCPMessage |
|
73 // |
|
74 // For receiving the message with a connectionless socket. |
|
75 // This is done if no DHCP Server address was found with the Symbian way. |
|
76 // Then we try it with Broadcast messages. |
|
77 // --------------------------------------------------------------------------- |
|
78 // |
|
79 void CDhcpPsySocketListener::RcvDHCPMessageConnectionlessL(TRequestStatus& aStatus) |
|
80 { |
|
81 TRACESTRING( "CDhcpPsySocketListener::RcvDHCPMessageConnectionlessL" ); |
|
82 aStatus = KRequestPending; |
|
83 iClientStatus = &aStatus; |
|
84 iIsConnectionless = ETrue; |
|
85 iRcvdDataHeapBufferPtr = HBufC8::NewL( KDhcpPacketLength ); |
|
86 iRcvdDataBuffer.Set( iRcvdDataHeapBufferPtr->Des() ); |
|
87 iRcvdDataBuffer.FillZ(); |
|
88 iAddress.SetPort( KDhcpDefaultCliPort ); |
|
89 iSocket->RecvFrom( iRcvdDataBuffer, |
|
90 iAddress, |
|
91 NULL, |
|
92 iStatus, |
|
93 iLen ); |
|
94 StartTimer (); |
|
95 SetActive(); |
|
96 } |
|
97 |
|
98 // --------------------------------------------------------------------------- |
|
99 // CDhcpPsySocketListener::RcvDHCPMessage |
|
100 // |
|
101 // For receiving DHCP message with a connected socket. If a DHCP server was |
|
102 // found and a bind could be done. |
|
103 // --------------------------------------------------------------------------- |
|
104 // |
|
105 void CDhcpPsySocketListener::RcvDHCPMessage(TRequestStatus& aStatus) |
|
106 { |
|
107 TRACESTRING( "CDhcpPsySocketListener::RcvDHCPMessage" ); |
|
108 aStatus = KRequestPending; |
|
109 iClientStatus = &aStatus; |
|
110 iIsConnectionless = EFalse; |
|
111 iSocket->Recv( iAckPckg, 0 , iStatus, iLen ); |
|
112 StartTimer (); |
|
113 SetActive(); |
|
114 } |
|
115 |
|
116 // --------------------------------------------------------------------------- |
|
117 // CDhcpPsySocketListener::StartTimer |
|
118 // |
|
119 // Start timeout control for making sure that used client thread doesn't halt |
|
120 // --------------------------------------------------------------------------- |
|
121 // |
|
122 void CDhcpPsySocketListener::StartTimer () |
|
123 { |
|
124 TRACESTRING( "CDhcpPsySocketListener::StartTimer" ); |
|
125 // Start the periodic timer, when ever the time elapsed |
|
126 // the PeriodicTimerCallBack() will get called. |
|
127 iPeriodicTimer->Start(KDhcpPeriodicTimerIntervalOneAndHalfSec, |
|
128 KDhcpPeriodicTimerIntervalOneAndHalfSec, |
|
129 TCallBack(PeriodicTimerCallBack, this)); |
|
130 } |
|
131 |
|
132 // --------------------------------------------------------------------------- |
|
133 // RunL |
|
134 // --------------------------------------------------------------------------- |
|
135 // |
|
136 void CDhcpPsySocketListener::RunL() |
|
137 { |
|
138 TRACESTRING2( "CDhcpPsySocketListener::RunL, %d", iStatus.Int() ); |
|
139 TInt result = iStatus.Int(); |
|
140 iPeriodicTimer->Cancel(); |
|
141 if (result==KErrNone) |
|
142 { |
|
143 if ( iIsConnectionless ) |
|
144 { |
|
145 iAckPckg.Copy( iRcvdDataHeapBufferPtr->Des() ); |
|
146 } |
|
147 if (CheckAckXid ()) |
|
148 { |
|
149 // Checks also that content is valid for location parsing. |
|
150 result = iAckPckg.ParseDHCPAck(); |
|
151 } |
|
152 } |
|
153 TRequestStatus *status = iClientStatus; |
|
154 User::RequestComplete (status, result); |
|
155 } |
|
156 |
|
157 // --------------------------------------------------------------------------- |
|
158 // Return location civic information for caller |
|
159 // --------------------------------------------------------------------------- |
|
160 // |
|
161 const TDesC8& CDhcpPsySocketListener::LocationCivicInformation () |
|
162 { |
|
163 TRACESTRING( "CDhcpPsySocketListener::LocationCivicInformation" ); |
|
164 return iAckPckg.iCivicAddress; |
|
165 } |
|
166 |
|
167 // --------------------------------------------------------------------------- |
|
168 // Return geoConfig information for caller |
|
169 // --------------------------------------------------------------------------- |
|
170 // |
|
171 const TDesC8& CDhcpPsySocketListener::GeoConfigDhcpInformation () |
|
172 { |
|
173 TRACESTRING( "CDhcpPsySocketListener::GeoConfigDhcpInformation" ); |
|
174 return iAckPckg.iGeoConf; |
|
175 } |
|
176 |
|
177 // --------------------------------------------------------------------------- |
|
178 // Set transaction action id to follow |
|
179 // --------------------------------------------------------------------------- |
|
180 // |
|
181 void CDhcpPsySocketListener::SetTransActionIdToFollow (TUint32 aXid) |
|
182 { |
|
183 TRACESTRING( "CDhcpPsySocketListener::SetTransActionIdToFollow" ); |
|
184 iXid = aXid; |
|
185 } |
|
186 |
|
187 // --------------------------------------------------------------------------- |
|
188 // CDhcpPsySocketListener::CheckAckXid |
|
189 // |
|
190 // For checking if the XID (identifier of the DHCP message) of the received |
|
191 // ACK - message matches the XID of the INFORM that was sent. |
|
192 // --------------------------------------------------------------------------- |
|
193 // |
|
194 TBool CDhcpPsySocketListener::CheckAckXid() |
|
195 { |
|
196 TRACESTRING( "CDhcpPsySocketListener::CheckAckXID" ); |
|
197 TBool retValue = EFalse; |
|
198 // Check if the message is the DHCP Ack that we wanted. |
|
199 // the length of the packet needs to be over 8 because otherwise |
|
200 // this leaves with error code. |
|
201 TRACESTRING2( "CDhcpPsySocketListener::CheckAckXID, ack length %d", iAckPckg.Length() ); |
|
202 if ( iAckPckg.Length() > KDhcpSizeOfMinXIDPacket ) |
|
203 { |
|
204 TUint32 ackXid = 0; |
|
205 // Copy the XID field from the message (4 octets from the 4:th octet) |
|
206 TPtrC8 xidPtr ( iAckPckg.Mid( KDhcpLocationOfXIDField, KDhcpLengthOfXIDField ) ); |
|
207 ackXid = BigEndian::Get32(xidPtr.Ptr()); |
|
208 // Compare the XID values |
|
209 if (ackXid == iXid) |
|
210 { |
|
211 TRACESTRING( "CDhcpPsySocketListener::CheckAckXID, true" ); |
|
212 retValue = ETrue; |
|
213 } |
|
214 } |
|
215 return retValue; |
|
216 } |
|
217 |
|
218 // --------------------------------------------------------------------------- |
|
219 // CDhcpPsySocketListener::DoCancel |
|
220 // --------------------------------------------------------------------------- |
|
221 // |
|
222 void CDhcpPsySocketListener::DoCancel() |
|
223 { |
|
224 TRACESTRING( "CDhcpPsySocketListener::DoCancel" ); |
|
225 iPeriodicTimer->Cancel(); |
|
226 iSocket->CancelRecv(); |
|
227 } |
|
228 |
|
229 // --------------------------------------------------------------------------- |
|
230 // CDhcpPsySocketListener::ConstructL |
|
231 // --------------------------------------------------------------------------- |
|
232 // |
|
233 void CDhcpPsySocketListener::ConstructL() |
|
234 { |
|
235 TRACESTRING ( "CDhcpPsySocketListener::ConstructL "); |
|
236 // Initialize the periodic timer. |
|
237 iPeriodicTimer = CPeriodic::NewL(CActive::EPriorityIdle); |
|
238 } |
|
239 |
|
240 // ---------------------------------------------------------------------------- |
|
241 // CDhcpPsySocketListener::PeriodicTimerCallBack |
|
242 // ---------------------------------------------------------------------------- |
|
243 // |
|
244 TInt CDhcpPsySocketListener::PeriodicTimerCallBack(TAny* aAny) |
|
245 { |
|
246 TRACESTRING ( "CDhcpPsySocketListener::PeriodicTimerCallBack "); |
|
247 CDhcpPsySocketListener* self = STATIC_CAST(CDhcpPsySocketListener*, aAny); |
|
248 // Cancel outstanding requests |
|
249 self->CancelOutstandigRequest(); |
|
250 return KErrNone; |
|
251 } |
|
252 |
|
253 // ---------------------------------------------------------------------------- |
|
254 // CDhcpPsySocketListener::CancelOutstandigRequest |
|
255 // ---------------------------------------------------------------------------- |
|
256 // |
|
257 void CDhcpPsySocketListener::CancelOutstandigRequest () |
|
258 { |
|
259 TRACESTRING ( "CDhcpPsySocketListener::CancelOutstandigRequest "); |
|
260 // Will cause outstanding request to complete prematurely |
|
261 iSocket->CancelRecv(); |
|
262 } |
|
263 |