|
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 |
|
19 package com.nokia.mj.impl.datagram; |
|
20 |
|
21 import java.io.*; |
|
22 import javax.microedition.io.*; |
|
23 import com.nokia.mj.impl.gcf.utils.UrlParser; |
|
24 import com.nokia.mj.impl.utils.Logger; |
|
25 import com.nokia.mj.impl.rt.support.Finalizer; |
|
26 import com.nokia.mj.impl.rt.support.ApplicationUtils; |
|
27 import com.nokia.mj.impl.rt.support.ShutdownListener; |
|
28 import com.nokia.mj.impl.gcf.protocol.datagram.DatagramPermissionImpl; |
|
29 import com.nokia.mj.impl.connectionmanager.ConnectionManager; |
|
30 import com.nokia.mj.impl.connectionmanager.AccessPoint; |
|
31 import com.nokia.mj.impl.rt.support.ApplicationInfo; |
|
32 import com.nokia.mj.impl.utils.Uid; |
|
33 |
|
34 /** |
|
35 * UDP DatagramConnection Implementation class. |
|
36 * |
|
37 */ |
|
38 |
|
39 public class UDPDatagramConnectionImpl implements UDPDatagramConnection |
|
40 { |
|
41 private int iNativePeerHandle; |
|
42 private UrlParser iUri; |
|
43 private boolean iConnectionOpen = true; |
|
44 private Finalizer iFinalizer; |
|
45 private static final String DATAGRAM_PROTOCOL = "datagram"; |
|
46 private static final int MAX_DATAGRAM_SIZE = 65535; |
|
47 private static final int NOMINAL_DATAGRAM_SIZE = 256; |
|
48 private ConnectionManager iCmInstance = null; |
|
49 private AccessPoint iApn = null; |
|
50 private String iFullUrl = null; |
|
51 |
|
52 /** |
|
53 * Constructs the UDPDatagramConnectionImpl. |
|
54 * |
|
55 * @param aUri the uri to which udp connection is opened |
|
56 * @param aMode the with which udp datagram connection is opened |
|
57 * @param aTimeout the with period for the connection |
|
58 * @throws IOException in case of any IO errors |
|
59 */ |
|
60 |
|
61 public UDPDatagramConnectionImpl(String aUri, int aMode, boolean aTimeout) |
|
62 throws IOException |
|
63 { |
|
64 |
|
65 Logger.LOG(Logger.ESOCKET,Logger.EInfo," +UDPDatagramConnectionImpl(): aUri = " + aUri); |
|
66 int retVal = 0; |
|
67 |
|
68 int retval[] = new int[1]; |
|
69 |
|
70 String apnstring = null; |
|
71 String urls = null; |
|
72 int apnid = -1; |
|
73 int index = -1; |
|
74 iFullUrl = "datagram:"+aUri; |
|
75 |
|
76 index = aUri.indexOf(";nokia_netid="); |
|
77 if (index != -1) |
|
78 { |
|
79 apnstring = aUri.substring(index); |
|
80 int equalindex = apnstring.indexOf('='); |
|
81 if (equalindex != -1) |
|
82 { |
|
83 String temp = apnstring.substring(equalindex+1); |
|
84 try |
|
85 { |
|
86 apnid = Integer.parseInt(temp); |
|
87 } |
|
88 catch (NumberFormatException e) |
|
89 { |
|
90 throw new IllegalArgumentException("Invalid URL: "+iFullUrl); |
|
91 } |
|
92 } |
|
93 else |
|
94 { |
|
95 throw new IllegalArgumentException("Invalid URL: "+iFullUrl); |
|
96 } |
|
97 urls = aUri.substring(0, index); |
|
98 } |
|
99 else |
|
100 { |
|
101 index = aUri.indexOf(";nokia_apnid="); |
|
102 if (index != -1) |
|
103 { |
|
104 apnstring = aUri.substring(index); |
|
105 int equalindex = apnstring.indexOf('='); |
|
106 if (equalindex != -1) |
|
107 { |
|
108 String temp = apnstring.substring(equalindex+1); |
|
109 try |
|
110 { |
|
111 apnid = Integer.parseInt(temp); |
|
112 } |
|
113 catch (NumberFormatException e) |
|
114 { |
|
115 throw new IllegalArgumentException("Invalid URL: "+iFullUrl); |
|
116 } |
|
117 } |
|
118 else |
|
119 { |
|
120 throw new IllegalArgumentException("Invalid URL: "+iFullUrl); |
|
121 } |
|
122 urls = aUri.substring(0, index); |
|
123 } |
|
124 else |
|
125 { |
|
126 urls = aUri; |
|
127 } |
|
128 } |
|
129 Logger.LOG(Logger.ESOCKET, Logger.EInfo,"UDPDatagramConnectionImpl -after removing nokia_apnid : "+urls); |
|
130 |
|
131 if (urls.equals("//:")) |
|
132 { |
|
133 String temp = "datagram:"+urls; |
|
134 |
|
135 /* security related stuff */ |
|
136 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
137 DatagramPermissionImpl per = new DatagramPermissionImpl("datagram://"); |
|
138 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
139 "calling check permissions from UDPDatagramConnectionImpl"); |
|
140 appUtils.checkPermission(per); |
|
141 /* security related stuff */ |
|
142 |
|
143 iNativePeerHandle = _createNativePeer(temp,aMode,"",0); |
|
144 } |
|
145 else |
|
146 { |
|
147 iUri = new UrlParser(DATAGRAM_PROTOCOL, urls); |
|
148 |
|
149 if (iUri.port == -1) |
|
150 { |
|
151 /* client connecction should have a port number */ |
|
152 throw new IllegalArgumentException("Invalid URL: "+iFullUrl); |
|
153 } |
|
154 /* check for restricted ports */ |
|
155 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
156 "port = "+iUri.port); |
|
157 |
|
158 if (iUri.getPort() == 9200 || iUri.getPort() == 9201 || iUri.getPort() == 9202 || iUri.getPort() == 9203) |
|
159 { |
|
160 if (ApplicationInfo.getInstance().getRuntimeType().equals(ApplicationInfo.RUNTIME_MIDP) == true) |
|
161 { |
|
162 if ((ApplicationInfo.getInstance().getProtectionDomain().equals(ApplicationInfo.UNIDENTIFIED_THIRD_PARTY_DOMAIN)) == true) |
|
163 { |
|
164 Logger.LOG(Logger.ESOCKET, Logger.EInfo,"Throwing security exception for restricted port"); |
|
165 throw new SecurityException("Unable to open datagram connection: port " +iUri.getPort()+ " is restricted"); |
|
166 } |
|
167 } |
|
168 } |
|
169 |
|
170 if (iUri.host == null) |
|
171 { |
|
172 /* security related stuff, server mode datagram connection */ |
|
173 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
174 DatagramPermissionImpl per = new DatagramPermissionImpl("datagram://"); |
|
175 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
176 "calling check permissions from UDPDatagramConnectionImpl"); |
|
177 appUtils.checkPermission(per); |
|
178 /* security related stuff */ |
|
179 |
|
180 iNativePeerHandle = _createNativePeer(iUri.toString(),aMode,"",iUri.port); |
|
181 } |
|
182 else |
|
183 { |
|
184 /* security related stuff, client mode datagram connection */ |
|
185 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
186 DatagramPermissionImpl per = new DatagramPermissionImpl("datagram://*"); |
|
187 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
188 "calling check permissions from UDPDatagramConnectionImpl"); |
|
189 appUtils.checkPermission(per); |
|
190 /* security related stuff */ |
|
191 |
|
192 iNativePeerHandle = _createNativePeer(iUri.toString(),aMode,iUri.host,iUri.port); |
|
193 } |
|
194 } |
|
195 if (iNativePeerHandle == 0) |
|
196 { |
|
197 throw new IOException("Unable to open datagram connection.Creating native peer failed"); |
|
198 } |
|
199 |
|
200 // remove comments if open c patch available |
|
201 iCmInstance = ConnectionManager.getInstance(); |
|
202 Logger.LOG(Logger.ESOCKET, Logger.EInfo,"after getting ConnectionManager instance"); |
|
203 // get application suite uid |
|
204 try |
|
205 { |
|
206 Uid appSuite = ApplicationInfo.getInstance().getSuiteUid(); |
|
207 try |
|
208 { |
|
209 // remove comments if open c patch available |
|
210 iApn = iCmInstance.getNetworkAccessPoint(appSuite, aUri); |
|
211 Logger.LOG(Logger.ESOCKET, Logger.EInfo,"iApn.getType = "+iApn.getType()+ " iApn.getNapId= "+iApn.getNapId()); |
|
212 } |
|
213 catch (Exception e) |
|
214 { |
|
215 Logger.LOG(Logger.ESOCKET, Logger.EInfo,"getNetworkAccessPoint threw Exception"); |
|
216 } |
|
217 |
|
218 } |
|
219 catch (Exception e) |
|
220 { |
|
221 Logger.LOG(Logger.ESOCKET, Logger.EInfo,"getSuiteUid exception "); |
|
222 } |
|
223 |
|
224 if (iApn != null) |
|
225 { |
|
226 retVal = _openConnection(iNativePeerHandle,iApn.getType(),iApn.getNapId(), retval); |
|
227 } |
|
228 else |
|
229 { |
|
230 retVal = _openConnection(iNativePeerHandle, -1, -1, retval); |
|
231 } |
|
232 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
233 "UDPDatagramConnectionImpl::UDPDatagramConnectionImpl(): _openConnection return value " |
|
234 + retVal); |
|
235 if (iCmInstance != null) |
|
236 { |
|
237 if (retval[0] < 0) |
|
238 { |
|
239 //reset connection manager |
|
240 iCmInstance.reset(); |
|
241 } |
|
242 } |
|
243 |
|
244 if (retVal < 0) |
|
245 { |
|
246 throw new IOException("Unable to open datagram connection. POSIX error code: "+retVal); |
|
247 } |
|
248 |
|
249 iFinalizer = registerforFinalization(); |
|
250 |
|
251 setShutdownListener(); |
|
252 Logger.LOG(Logger.ESOCKET,Logger.EInfo," --UDPDatagramConnectionImpl()"); |
|
253 } |
|
254 |
|
255 /** |
|
256 * Registers for shutdown listener |
|
257 */ |
|
258 private void setShutdownListener() |
|
259 { |
|
260 // Get the instance of ApplicationUtils. |
|
261 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
262 |
|
263 // Get the name of the application. |
|
264 appUtils.addShutdownListener(new ShutdownListener() |
|
265 { |
|
266 public void shuttingDown() |
|
267 { |
|
268 try |
|
269 { |
|
270 close();// Do cleaning... |
|
271 } |
|
272 catch (IOException ex) |
|
273 { |
|
274 // catch the exception and call dispose |
|
275 } |
|
276 if (iNativePeerHandle != 0) |
|
277 { |
|
278 _dispose(iNativePeerHandle); |
|
279 iNativePeerHandle = 0; |
|
280 } |
|
281 } |
|
282 |
|
283 }); |
|
284 } |
|
285 /** |
|
286 * Get the local socket address of this UDPDatagram connection. |
|
287 * |
|
288 * @return the local address |
|
289 * @throws IOException in case of any IO errors |
|
290 */ |
|
291 |
|
292 public String getLocalAddress() throws IOException |
|
293 { |
|
294 String[] address = new String[1]; |
|
295 int retVal; |
|
296 if (!iConnectionOpen) |
|
297 { |
|
298 throw new IOException("getLocalAddress failed: connection is already closed"); |
|
299 } |
|
300 retVal = _getLocalAddress(iNativePeerHandle, address); |
|
301 if (retVal < 0) |
|
302 { |
|
303 throw new IOException("getLocalAddress method failed.Posix error code: " + retVal); |
|
304 } |
|
305 else |
|
306 { |
|
307 return address[0]; |
|
308 } |
|
309 } |
|
310 |
|
311 /** |
|
312 * Get the local port of this UDPDatagram connection. |
|
313 * |
|
314 * @return the local port |
|
315 * @throws IOException in case of any IO errors |
|
316 */ |
|
317 |
|
318 public int getLocalPort() throws IOException |
|
319 { |
|
320 int retVal; |
|
321 if (!iConnectionOpen) |
|
322 { |
|
323 throw new IOException("getLocalPort failed: connection is already closed"); |
|
324 } |
|
325 retVal = _getLocalPort(iNativePeerHandle); |
|
326 if (retVal < 0) |
|
327 { |
|
328 throw new IOException("getLocalPort method failed.Posix error code: " + retVal); |
|
329 } |
|
330 else |
|
331 { |
|
332 return retVal; |
|
333 } |
|
334 } |
|
335 |
|
336 /** |
|
337 * Close the secure connection. |
|
338 * |
|
339 * @throws IOException in case of any IO errors |
|
340 */ |
|
341 |
|
342 public synchronized void close() throws IOException |
|
343 { |
|
344 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
345 "+UDPDatagramConnectionImpl::Close()"); |
|
346 if (iConnectionOpen == true) |
|
347 { |
|
348 iConnectionOpen = false; |
|
349 int ret = _close(iNativePeerHandle); |
|
350 if (ret != 0) |
|
351 { |
|
352 if (ret == -4) |
|
353 { |
|
354 // if recieve is blocked when close is called |
|
355 throw new InterruptedIOException(); |
|
356 } |
|
357 else |
|
358 { |
|
359 throw new IOException("close method failed.Posix error code: " + ret); |
|
360 } |
|
361 } |
|
362 } |
|
363 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
364 "-UDPDatagramConnectionImpl::Close()"); |
|
365 } |
|
366 |
|
367 /** |
|
368 * Please refer JSR 118. |
|
369 */ |
|
370 |
|
371 public int getMaximumLength() throws IOException |
|
372 { |
|
373 if (!iConnectionOpen) |
|
374 { |
|
375 throw new IOException("getMaximumLength failed: connection is already closed"); |
|
376 } |
|
377 return MAX_DATAGRAM_SIZE; |
|
378 } |
|
379 |
|
380 /** |
|
381 * Please refer JSR 118. |
|
382 */ |
|
383 |
|
384 public int getNominalLength() throws IOException |
|
385 { |
|
386 if (!iConnectionOpen) |
|
387 { |
|
388 throw new IOException("getNominalLength failed: connection is already closed"); |
|
389 } |
|
390 return NOMINAL_DATAGRAM_SIZE; |
|
391 } |
|
392 |
|
393 /** |
|
394 * Please refer JSR 118. |
|
395 */ |
|
396 |
|
397 public void send(Datagram aDgram) throws IOException |
|
398 { |
|
399 |
|
400 int retVal; |
|
401 if (!iConnectionOpen) |
|
402 { |
|
403 throw new IOException("send failed: connection is already closed"); |
|
404 } |
|
405 String addr = aDgram.getAddress(); |
|
406 UrlParser url1; |
|
407 if (addr == null) |
|
408 { |
|
409 url1 = iUri; // address from the connector.open uri |
|
410 } |
|
411 else |
|
412 { |
|
413 url1 = new UrlParser(addr); |
|
414 |
|
415 if (url1.getPort() == 9200 || url1.getPort() == 9201 || url1.getPort() == 9202 || url1.getPort() == 9203) |
|
416 { |
|
417 if ((ApplicationInfo.getInstance().getProtectionDomain().equals(ApplicationInfo.UNIDENTIFIED_THIRD_PARTY_DOMAIN)) == true) |
|
418 { |
|
419 Logger.LOG(Logger.ESOCKET, Logger.EInfo,"Throwing secuirty exception for restricted port"); |
|
420 throw new SecurityException("Unable to open datagram connection: port " +url1.getPort()+ " is restricted"); |
|
421 } |
|
422 } |
|
423 } |
|
424 |
|
425 retVal = _send(iNativePeerHandle, aDgram.getData(), aDgram |
|
426 .getOffset(), aDgram.getLength(), url1.host, url1.port); |
|
427 |
|
428 if (retVal < 0) |
|
429 { |
|
430 throw new IOException("send method failed.Posix error code: " + retVal); |
|
431 } |
|
432 |
|
433 } |
|
434 |
|
435 /** |
|
436 * Please refer JSR 118. |
|
437 */ |
|
438 |
|
439 public void receive(Datagram aDgram) throws IOException |
|
440 { |
|
441 String addr = new String(" "); |
|
442 String[] senderAddr = new String[1]; |
|
443 int[] senderPort = new int[1]; |
|
444 int port = 0; |
|
445 int retVal; |
|
446 |
|
447 if (!iConnectionOpen) |
|
448 { |
|
449 throw new IOException("receive failed: connection is already closed"); |
|
450 } |
|
451 |
|
452 |
|
453 retVal = _receive(iNativePeerHandle, aDgram.getData(), aDgram |
|
454 .getOffset(), aDgram.getLength(), senderAddr, senderPort); |
|
455 |
|
456 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
457 "UDPDatagramConnectionImpl.java recieve returned : "+retVal); |
|
458 if (retVal < 0) |
|
459 { |
|
460 throw new IOException("receive method failed.Posix error code: " + retVal); |
|
461 } |
|
462 Logger.LOG(Logger.ESOCKET, Logger.EInfo, "addr = " |
|
463 + senderAddr[0] + "port = " + senderPort[0] |
|
464 + "recieve retval = " + retVal); |
|
465 StringBuffer recvurl = new StringBuffer(); |
|
466 recvurl.append(DATAGRAM_PROTOCOL + "://"); |
|
467 recvurl.append(senderAddr[0]); |
|
468 recvurl.append(":"); |
|
469 |
|
470 recvurl.append(senderPort[0]); |
|
471 Logger.LOG(Logger.ESOCKET, Logger.EInfo, "recvurl = " + recvurl); |
|
472 aDgram.setAddress(recvurl.toString()); |
|
473 aDgram.setLength(retVal); |
|
474 |
|
475 } |
|
476 |
|
477 /** |
|
478 * Please refer JSR 118. |
|
479 */ |
|
480 |
|
481 public Datagram newDatagram(int aSize) throws IOException |
|
482 { |
|
483 return newDatagram(aSize, null); |
|
484 } |
|
485 |
|
486 /** |
|
487 * Please refer JSR 118. |
|
488 */ |
|
489 public Datagram newDatagram(int aSize, String aAddr) throws IOException |
|
490 { |
|
491 if (aSize < 0) |
|
492 { |
|
493 throw new IllegalArgumentException("Invalid argument in newDatagram method"); |
|
494 } |
|
495 byte[] buf = new byte[aSize]; |
|
496 return newDatagram(buf, aSize, aAddr); |
|
497 } |
|
498 |
|
499 /** |
|
500 * Please refer JSR 118. |
|
501 */ |
|
502 |
|
503 public Datagram newDatagram(byte[] aBuf, int aSize) throws IOException |
|
504 { |
|
505 return newDatagram(aBuf, aSize, null); |
|
506 } |
|
507 |
|
508 /** |
|
509 * Please refer JSR 118. |
|
510 */ |
|
511 |
|
512 public Datagram newDatagram(byte[] aBuf, int aSize, String aAddr) |
|
513 throws IOException |
|
514 { |
|
515 |
|
516 if (!iConnectionOpen) |
|
517 { |
|
518 throw new IOException("newDatagram failed: connection is already closed"); |
|
519 } |
|
520 if (aBuf == null) |
|
521 { |
|
522 throw new IllegalArgumentException("Invalid argument in newDatagram method"); |
|
523 } |
|
524 if (aAddr != null) |
|
525 { |
|
526 UrlParser urlvalidation = new UrlParser(aAddr); |
|
527 } |
|
528 DatagramImpl t = new DatagramImpl(aBuf, aSize, aAddr); |
|
529 return t; |
|
530 } |
|
531 |
|
532 Finalizer registerforFinalization() |
|
533 { |
|
534 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
535 "creating a datagram finalizer object "); |
|
536 return new Finalizer() |
|
537 { |
|
538 public void finalizeImpl() |
|
539 { |
|
540 doFinalize(); |
|
541 } |
|
542 }; |
|
543 } |
|
544 |
|
545 public void doFinalize() |
|
546 { |
|
547 Logger.LOG(Logger.ESOCKET, Logger.EInfo, |
|
548 "datagram doFinalize() called :"); |
|
549 if (iConnectionOpen == true) |
|
550 { |
|
551 try |
|
552 { |
|
553 close(); |
|
554 } |
|
555 catch (IOException e) |
|
556 { |
|
557 // catch the exception and call dispose |
|
558 } |
|
559 } |
|
560 if (iNativePeerHandle != 0) |
|
561 { |
|
562 _dispose(iNativePeerHandle); |
|
563 iNativePeerHandle = 0; |
|
564 } |
|
565 } |
|
566 // Native calls |
|
567 private native int _createNativePeer(String aUri, int aMode, String host, |
|
568 int port); |
|
569 private native int _openConnection(int iNativePeerHandle, int aType, int aApn, int[] retval); |
|
570 private native int _send(int iNativePeerHandle, byte[] buf, int offset, |
|
571 int length, String host, int port); |
|
572 private native int _receive(int iNativePeerHandle, byte[] buf, int offset, |
|
573 int length, String[] senderAddr, int[] senderPort); |
|
574 private native int _getLocalAddress(int iNativePeerHandle, String[] address); |
|
575 private native int _getLocalPort(int iNativePeerHandle); |
|
576 private native int _close(int iNativePeerHandle); |
|
577 private native void _dispose(int iNativePeerHandle); |
|
578 |
|
579 } |