View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.transport.nio;
21  
22  import java.io.IOException;
23  import java.net.SocketAddress;
24  import java.net.SocketException;
25  import java.nio.channels.DatagramChannel;
26  
27  import org.apache.mina.api.IdleStatus;
28  import org.apache.mina.api.IoFuture;
29  import org.apache.mina.api.IoSession;
30  import org.apache.mina.api.MinaRuntimeException;
31  import org.apache.mina.service.executor.IoHandlerExecutor;
32  import org.apache.mina.service.idlechecker.IndexedIdleChecker;
33  import org.apache.mina.transport.ConnectFuture;
34  import org.apache.mina.transport.udp.AbstractUdpClient;
35  import org.apache.mina.transport.udp.UdpSessionConfig;
36  import org.apache.mina.util.Assert;
37  
38  /**
39   * This class implements a UDP NIO based client.
40   * 
41   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
42   */
43  public class NioUdpClient extends AbstractUdpClient {
44  
45      /** the SelectorLoop for handling read/write session events */
46      // This is final, so that we know if it's not initialized
47      private final SelectorLoopPool readWriteSelectorPool;
48  
49      private final IndexedIdleChecker idleChecker = new IndexedIdleChecker();
50  
51      /**
52       * Create a new instance of NioUdpClient
53       */
54      public NioUdpClient() {
55          this(null);
56      }
57  
58      /**
59       * Create a new instance of NioUdpClient
60       */
61      public NioUdpClient(IoHandlerExecutor ioHandlerExecutor) {
62          super(ioHandlerExecutor);
63          readWriteSelectorPool = new FixedSelectorLoopPool("Client", 2);
64          idleChecker.start();
65      }
66  
67      /**
68       * {@inheritDoc}
69       */
70      @Override
71      public IoFuture<IoSession> connect(SocketAddress remoteAddress) {
72          Assert.assertNotNull(remoteAddress, "remoteAddress");
73  
74          DatagramChannel ch;
75          try {
76              ch = DatagramChannel.open();
77          } catch (IOException e) {
78              throw new MinaRuntimeException("can't create a new socket, out of file descriptors ?", e);
79          }
80          try {
81              ch.configureBlocking(false);
82          } catch (IOException e) {
83              throw new MinaRuntimeException("can't configure socket as non-blocking", e);
84          }
85  
86          UdpSessionConfig config = getSessionConfig();
87  
88          NioSelectorLoop loop = (NioSelectorLoop) readWriteSelectorPool.getSelectorLoop();
89  
90          NioUdpSession session = new NioUdpSession(this, idleChecker, ch, null, remoteAddress, loop);
91  
92          session.setConnected();
93  
94          // apply idle configuration
95          session.getConfig().setIdleTimeInMillis(IdleStatus.READ_IDLE, config.getIdleTimeInMillis(IdleStatus.READ_IDLE));
96          session.getConfig().setIdleTimeInMillis(IdleStatus.WRITE_IDLE,
97                  config.getIdleTimeInMillis(IdleStatus.WRITE_IDLE));
98  
99          // Manage the Idle status
100         idleChecker.sessionRead(session, System.currentTimeMillis());
101         idleChecker.sessionWritten(session, System.currentTimeMillis());
102 
103         // apply the default service socket configuration
104 
105         Boolean reuseAddress = config.isReuseAddress();
106 
107         if (reuseAddress != null) {
108             session.getConfig().setReuseAddress(reuseAddress);
109         }
110 
111         Integer readBufferSize = config.getReadBufferSize();
112 
113         if (readBufferSize != null) {
114             session.getConfig().setReadBufferSize(readBufferSize);
115         } else {
116             int rcvBufferSize;
117             try {
118                 rcvBufferSize = ch.socket().getReceiveBufferSize();
119                 session.getConfig().setReadBufferSize(rcvBufferSize);
120 
121             } catch (SocketException e) {
122                 throw new MinaRuntimeException("can't configure socket receive buffer size", e);
123             }
124         }
125 
126         Integer sendBufferSize = config.getSendBufferSize();
127 
128         if (sendBufferSize != null) {
129             session.getConfig().setSendBufferSize(sendBufferSize);
130         } else {
131             int sndBufferSize;
132             try {
133                 sndBufferSize = ch.socket().getSendBufferSize();
134                 session.getConfig().setSendBufferSize(sndBufferSize);
135             } catch (SocketException e) {
136                 throw new MinaRuntimeException("can't configure socket send buffe size", e);
137             }
138         }
139 
140         Integer trafficClass = config.getTrafficClass();
141 
142         if (trafficClass != null) {
143             session.getConfig().setTrafficClass(trafficClass);
144         }
145 
146         loop.register(false, false, true, false, session, ch, null);
147 
148         ConnectFuture cf = new ConnectFuture();
149         cf.complete(session);
150 
151         return cf;
152     }
153 
154     /**
155      * {@inheritDoc}
156      */
157     @Override
158     public IoFuture<IoSession> connect(SocketAddress remoteAddress, SocketAddress localAddress) {
159         throw new IllegalStateException("not supported for UDP");
160     }
161 }