1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.channel.socket.oio;
17
18 import static org.jboss.netty.channel.Channels.*;
19
20 import java.io.IOException;
21 import java.net.InetAddress;
22 import java.net.InetSocketAddress;
23 import java.net.MulticastSocket;
24 import java.net.NetworkInterface;
25 import java.net.SocketAddress;
26 import java.net.SocketException;
27
28 import org.jboss.netty.channel.AbstractChannel;
29 import org.jboss.netty.channel.ChannelException;
30 import org.jboss.netty.channel.ChannelFactory;
31 import org.jboss.netty.channel.ChannelFuture;
32 import org.jboss.netty.channel.ChannelPipeline;
33 import org.jboss.netty.channel.ChannelSink;
34 import org.jboss.netty.channel.socket.DatagramChannel;
35 import org.jboss.netty.channel.socket.DatagramChannelConfig;
36 import org.jboss.netty.channel.socket.DefaultDatagramChannelConfig;
37
38
39
40
41
42
43
44
45
46 final class OioDatagramChannel extends AbstractChannel
47 implements DatagramChannel {
48
49 final MulticastSocket socket;
50 final Object interestOpsLock = new Object();
51 private final DatagramChannelConfig config;
52 volatile Thread workerThread;
53 private volatile InetSocketAddress localAddress;
54 volatile InetSocketAddress remoteAddress;
55
56 OioDatagramChannel(
57 ChannelFactory factory,
58 ChannelPipeline pipeline,
59 ChannelSink sink) {
60
61 super(null, factory, pipeline, sink);
62
63 try {
64 socket = new MulticastSocket(null);
65 } catch (IOException e) {
66 throw new ChannelException("Failed to open a datagram socket.", e);
67 }
68
69 try {
70 socket.setSoTimeout(10);
71 socket.setBroadcast(false);
72 } catch (SocketException e) {
73 throw new ChannelException(
74 "Failed to configure the datagram socket timeout.", e);
75 }
76 config = new DefaultDatagramChannelConfig(socket);
77
78 fireChannelOpen(this);
79 }
80
81 public DatagramChannelConfig getConfig() {
82 return config;
83 }
84
85 public InetSocketAddress getLocalAddress() {
86 InetSocketAddress localAddress = this.localAddress;
87 if (localAddress == null) {
88 try {
89 this.localAddress = localAddress =
90 (InetSocketAddress) socket.getLocalSocketAddress();
91 } catch (Throwable t) {
92
93 return null;
94 }
95 }
96 return localAddress;
97 }
98
99 public InetSocketAddress getRemoteAddress() {
100 InetSocketAddress remoteAddress = this.remoteAddress;
101 if (remoteAddress == null) {
102 try {
103 this.remoteAddress = remoteAddress =
104 (InetSocketAddress) socket.getRemoteSocketAddress();
105 } catch (Throwable t) {
106
107 return null;
108 }
109 }
110 return remoteAddress;
111 }
112
113 public boolean isBound() {
114 return isOpen() && socket.isBound();
115 }
116
117 public boolean isConnected() {
118 return isOpen() && socket.isConnected();
119 }
120
121 @Override
122 protected boolean setClosed() {
123 return super.setClosed();
124 }
125
126 @Override
127 protected void setInterestOpsNow(int interestOps) {
128 super.setInterestOpsNow(interestOps);
129 }
130
131 @Override
132 public ChannelFuture write(Object message, SocketAddress remoteAddress) {
133 if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
134 return super.write(message, null);
135 } else {
136 return super.write(message, remoteAddress);
137 }
138 }
139
140 public void joinGroup(InetAddress multicastAddress) {
141 ensureBound();
142 try {
143 socket.joinGroup(multicastAddress);
144 } catch (IOException e) {
145 throw new ChannelException(e);
146 }
147 }
148
149 public void joinGroup(
150 InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
151 ensureBound();
152 try {
153 socket.joinGroup(multicastAddress, networkInterface);
154 } catch (IOException e) {
155 throw new ChannelException(e);
156 }
157 }
158
159 private void ensureBound() {
160 if (!isBound()) {
161 throw new IllegalStateException(
162 DatagramChannel.class.getName() +
163 " must be bound to join a group.");
164 }
165 }
166
167 public void leaveGroup(InetAddress multicastAddress) {
168 try {
169 socket.leaveGroup(multicastAddress);
170 } catch (IOException e) {
171 throw new ChannelException(e);
172 }
173 }
174
175 public void leaveGroup(
176 InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
177 try {
178 socket.leaveGroup(multicastAddress, networkInterface);
179 } catch (IOException e) {
180 throw new ChannelException(e);
181 }
182 }
183 }