|
1 /* |
|
2 * Copyright (c) 2008 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <sys/socket.h> |
|
19 #include <sys/select.h> |
|
20 #include <unistd.h> |
|
21 #include <errno.h> |
|
22 #include <arpa/inet.h> |
|
23 #include <netinet/in.h> |
|
24 #include <fcntl.h> |
|
25 #include <sys/stat.h> |
|
26 #include <sys/types.h> |
|
27 #include <sys/socket.h> |
|
28 #include <netinet/in.h> |
|
29 #include <wchar.h> |
|
30 #include <string.h> |
|
31 |
|
32 #include "logger.h" |
|
33 #include "connectionlistener.h" |
|
34 #include "javacommonutils.h" |
|
35 |
|
36 #include "datagramserverconnection.h" |
|
37 #include "datagramserverconnectionfactory.h" |
|
38 #include "pushexception.h" |
|
39 #include "pusherrorcodes.h" |
|
40 |
|
41 #define INVALID_SOCKET (-1) |
|
42 #define MAX_SIZE 256 |
|
43 #define BUFFER_SIZE 512 |
|
44 |
|
45 using namespace java::util; |
|
46 |
|
47 DatagramServerConnection::DatagramServerConnection() |
|
48 { |
|
49 LOG(ESOCKET, EInfo, "+DatagramServerConnection - default constructor"); |
|
50 mListener = NULL, |
|
51 mThreadId = 0; |
|
52 mKeepRunning = false; |
|
53 mListenDatagram = INVALID_SOCKET; |
|
54 mAcceptDatagram = INVALID_SOCKET; |
|
55 mPort = 0; |
|
56 mIsNormalServerConnection = true; |
|
57 mError = 0; |
|
58 mOpenMonitor = 0; |
|
59 } |
|
60 |
|
61 OS_EXPORT DatagramServerConnection::DatagramServerConnection( |
|
62 const std::wstring& aUri, const std::wstring& aFilter) : |
|
63 mListener(0), mThreadId(0), mKeepRunning(false), mListenDatagram( |
|
64 INVALID_SOCKET), mAcceptDatagram(INVALID_SOCKET), mUri(aUri), |
|
65 mFilter(aFilter), mPort(0) |
|
66 { |
|
67 JELOG2(ESOCKET); |
|
68 |
|
69 // sanity check for url |
|
70 ILOG1(ESOCKET, |
|
71 "++DatagramServerConnection::DatagramServerConnection() aUri = %s", |
|
72 aUri.c_str()); |
|
73 mIsNormalServerConnection = false; |
|
74 mIsAppRunning = false; |
|
75 mError = 0; |
|
76 mOpenMonitor = 0; |
|
77 |
|
78 if (0 == mOpenMonitor) |
|
79 { |
|
80 mOpenMonitor = Monitor::createMonitor(); |
|
81 } |
|
82 |
|
83 if (aUri.length() == 12) |
|
84 mPort = 0; |
|
85 else |
|
86 { |
|
87 std::wstring port = aUri.substr(12); // "datagram://:" |
|
88 mPort = JavaCommonUtils::wstringToInt(port); |
|
89 } |
|
90 LOG1(ESOCKET, EInfo, "created DatagramServerConnection on port %d", mPort); |
|
91 } |
|
92 |
|
93 OS_EXPORT DatagramServerConnection::~DatagramServerConnection() |
|
94 { |
|
95 if (mOpenMonitor) |
|
96 { |
|
97 delete mOpenMonitor; |
|
98 } |
|
99 JELOG2(ESOCKET); |
|
100 } |
|
101 |
|
102 OS_EXPORT void DatagramServerConnection::open(ConnectionListener* aListener) |
|
103 { |
|
104 JELOG2(ESOCKET); |
|
105 mListener = aListener; |
|
106 |
|
107 mKeepRunning = true; |
|
108 int rc = pthread_create(&mThreadId, NULL, |
|
109 DatagramServerConnection::listenThread, this); |
|
110 mOpenMonitor->wait(); |
|
111 |
|
112 ILOG2(ESOCKET,"after release in datagram rc = %dm mPort = %d",rc,mPort); |
|
113 if (rc < 0 || mError < 0) |
|
114 { |
|
115 ELOG1(ESOCKET,"ERROR!!! Datagram server conn already exists on Port %d : Open Failed",mPort); |
|
116 std::string errTxt("ERROR!!! Opening of Datagram Server failed "); |
|
117 throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR,errTxt,__FILE__, __FUNCTION__,__LINE__); |
|
118 } |
|
119 } |
|
120 |
|
121 void* DatagramServerConnection::listenThread(void* aParams) |
|
122 { |
|
123 JELOG2(ESOCKET); |
|
124 struct sockaddr_in sender_addr; |
|
125 sender_addr.sin_family = AF_INET; |
|
126 unsigned int size = sizeof(sender_addr); |
|
127 bool match = false; |
|
128 |
|
129 DatagramServerConnection* pThis = |
|
130 reinterpret_cast<DatagramServerConnection*>(aParams); |
|
131 |
|
132 pThis->mListenDatagram = pThis->open(pThis->mPort); |
|
133 |
|
134 if (pThis->mListenDatagram < 0) |
|
135 { |
|
136 pThis->mError = -errno; |
|
137 (pThis->mOpenMonitor)->notify(); |
|
138 pthread_exit(0); |
|
139 } |
|
140 (pThis->mOpenMonitor)->notify(); |
|
141 |
|
142 |
|
143 int rt = -1; |
|
144 char * addr = new char[MAX_SIZE]; |
|
145 |
|
146 if (rt < 0 && pThis->mKeepRunning) |
|
147 { |
|
148 char *buf = new char[BUFFER_SIZE]; |
|
149 // wchar_t * sender = new wchar_t[256]; |
|
150 char * sender = new char[256]; |
|
151 while (match == false) |
|
152 { |
|
153 rt = recvfrom(pThis->mListenDatagram, buf, BUFFER_SIZE, 0, |
|
154 (sockaddr*) &sender_addr, &size); |
|
155 |
|
156 strcpy(sender,inet_ntoa(sender_addr.sin_addr)); |
|
157 ILOG2(ESOCKET, "pThis->mListenDatagram = %d, port = %d",pThis-> mListenDatagram,pThis->mPort); |
|
158 |
|
159 // validate the filter |
|
160 /*if(strcmp((const char *)pThis->mFilter.c_str(),(const char *) NULL)== 0) |
|
161 { |
|
162 LOG(ESOCKET,EInfo,"filter is NULL"); |
|
163 match = true; |
|
164 } |
|
165 else |
|
166 { |
|
167 if( strcmp((const char *)"*",(const char *)pThis->mFilter.c_str()) == 0) |
|
168 { |
|
169 LOG(ESOCKET,EInfo,"filter = '*'"); |
|
170 match = true; |
|
171 } |
|
172 if( strcmp((const char *)"?",(const char *)pThis->mFilter.c_str()) == 0) |
|
173 { |
|
174 LOG(ESOCKET,EInfo,"filter = '?'"); |
|
175 match = true; |
|
176 } |
|
177 }*/ |
|
178 |
|
179 |
|
180 match = true; |
|
181 } |
|
182 } |
|
183 |
|
184 if (!(rt < 0)) // we have incoming connection |
|
185 { |
|
186 pThis->mAcceptDatagram = pThis->mListenDatagram; |
|
187 if (pThis->mIsAppRunning == true) |
|
188 { |
|
189 pThis->setActivityFlag(false); |
|
190 pthread_exit(0); |
|
191 } |
|
192 else |
|
193 { |
|
194 if (pThis->mListener) |
|
195 { |
|
196 pThis->mListener->msgArrived(); |
|
197 } |
|
198 pThis->setActivityFlag(true); |
|
199 } |
|
200 } |
|
201 return 0; |
|
202 } |
|
203 |
|
204 OS_EXPORT int DatagramServerConnection::open() |
|
205 { |
|
206 JELOG2(ESOCKET); |
|
207 |
|
208 mIsAppRunning = true; |
|
209 |
|
210 if (mKeepRunning) // we are listening for push connection |
|
211 { |
|
212 mKeepRunning = false; |
|
213 pthread_join(mThreadId, NULL); |
|
214 } |
|
215 else |
|
216 { |
|
217 mListenDatagram = open(mPort); |
|
218 } |
|
219 LOG2(ESOCKET,EInfo, "mListenDatagram = %d, mPort = %d", mListenDatagram, mPort); |
|
220 setActivityFlag(false); |
|
221 return mListenDatagram; |
|
222 } |
|
223 |
|
224 int DatagramServerConnection::open(int aPort) |
|
225 { |
|
226 JELOG2(ESOCKET); |
|
227 |
|
228 struct sockaddr_in addr; |
|
229 addr.sin_family = AF_INET; |
|
230 addr.sin_port = htons((unsigned short) aPort); |
|
231 addr.sin_addr.s_addr = htonl(INADDR_ANY); |
|
232 |
|
233 int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
|
234 if (fd == INVALID_SOCKET) |
|
235 { |
|
236 return -1; |
|
237 } |
|
238 |
|
239 addr.sin_addr.s_addr = htonl(INADDR_ANY); |
|
240 |
|
241 int res = bind(fd, (struct sockaddr*) &addr, sizeof(addr)); |
|
242 |
|
243 // when server is opened on dynamic port, append the port to the url |
|
244 /*if(mPort == 0) |
|
245 { |
|
246 mPort = addr.sin_port; |
|
247 LOG1(ESOCKET, EInfo, "dynamic port : %d", mPort); |
|
248 std::wstring portString = JavaCommonUtils::intToWstring(mPort); |
|
249 mUri.append(portString); |
|
250 LOG1(ESOCKET, EInfo, "after appending mUri with dynamic port : %s", mUri); |
|
251 }*/ |
|
252 LOG3(ESOCKET,EInfo, "server datgram sd = %dm bind returns %d, mPort = %d ", fd, res, mPort); |
|
253 if (res != -1) |
|
254 { |
|
255 return fd; |
|
256 } |
|
257 LOG1(ESOCKET,EInfo, "-errno : %d" , -errno); |
|
258 close(fd); |
|
259 return -1; |
|
260 } |
|
261 |
|
262 |
|
263 OS_EXPORT void DatagramServerConnection::close() |
|
264 { |
|
265 JELOG2(ESOCKET); |
|
266 |
|
267 |
|
268 |
|
269 ::close(mListenDatagram); |
|
270 ::close(mAcceptDatagram); |
|
271 |
|
272 if (mKeepRunning) // we are listening for push connection |
|
273 { |
|
274 mKeepRunning = false; |
|
275 pthread_join(mThreadId, NULL); |
|
276 } |
|
277 |
|
278 // reset members |
|
279 mListenDatagram = INVALID_SOCKET; |
|
280 mAcceptDatagram = INVALID_SOCKET; |
|
281 |
|
282 mListener = 0; |
|
283 mThreadId = 0; |
|
284 //mKeepRunning = false; |
|
285 } |
|
286 |
|
287 OS_EXPORT std::wstring DatagramServerConnection::getUri() const |
|
288 { |
|
289 LOG(ESOCKET,EInfo, "DatagramServerConnection::getUri() "); |
|
290 return mUri; |
|
291 } |
|
292 |
|
293 OS_EXPORT std::wstring DatagramServerConnection::getFilter() const |
|
294 { |
|
295 return mFilter; |
|
296 } |
|
297 |
|
298 OS_EXPORT void DatagramServerConnection::setFilter(const std::wstring& aFilter) |
|
299 { |
|
300 JELOG2(ESOCKET); |
|
301 mFilter = aFilter; |
|
302 } |
|
303 OS_EXPORT bool DatagramServerConnection::isNormalServerConnection() |
|
304 { |
|
305 return mIsNormalServerConnection; |
|
306 } |
|
307 |
|
308 OS_EXPORT void DatagramServerConnection::setNormalServerConnection() |
|
309 { |
|
310 LOG(ESOCKET,EInfo,"Push is enabled"); |
|
311 mIsNormalServerConnection = true; |
|
312 } |
|
313 int DatagramServerConnection::close(int fd) |
|
314 { |
|
315 return ::close(fd); |
|
316 } |
|
317 |
|
318 |
|
319 /** |
|
320 * SetActivityFlag method updates status whether |
|
321 * ServerConnection object has pending message(= message arrived but not yet read). |
|
322 * @param aFlag Updating logic of pending message flag: |
|
323 * - Set it 'true' when message arrives to the connection. |
|
324 * - Set it 'false' when ServerConnection::open() operation has been called. |
|
325 */ |
|
326 void DatagramServerConnection::setActivityFlag(bool aFlag) |
|
327 { |
|
328 DatagramServerConnectionFactory& scf = |
|
329 DatagramServerConnectionFactory::getFactory(); |
|
330 scf.setPendingMsgFlag(mUri, aFlag); |
|
331 } |