16 package com.sonycsl.echo;
18 import java.io.DataInputStream;
19 import java.io.DataOutputStream;
20 import java.io.IOException;
21 import java.net.DatagramPacket;
22 import java.net.InetAddress;
23 import java.net.InetSocketAddress;
24 import java.net.MulticastSocket;
25 import java.net.ServerSocket;
26 import java.net.Socket;
27 import java.util.ArrayList;
28 import java.util.Enumeration;
29 import java.util.HashMap;
30 import java.util.LinkedList;
31 import java.util.List;
33 import java.util.Queue;
34 import java.util.concurrent.ExecutorService;
35 import java.util.concurrent.Executors;
36 import java.util.concurrent.TimeUnit;
46 @SuppressWarnings(
"unused")
47 private static final String TAG = EchoSocket.class.getSimpleName();
54 private static final int PORT = 3610;
56 private static final Queue<EchoFrame> mSelfFrameQueue =
new LinkedList<EchoFrame>();
57 private static MulticastSocket sMulticastSocket;
58 private static InetAddress sMulticastAddress;
60 private static Thread sRecvThread;
63 private static ServerSocket sServerSocket;
64 private static ExecutorService sConnectedTCPSocketThreads;
66 private static HashMap<String, ArrayList<Socket>> sTCPSockets;
69 private static short sNextTID = 0;
73 private static class Receiver
implements Runnable {
76 while(!Thread.currentThread().isInterrupted()) {
80 }
catch (IOException e) {
84 receiveFrameFromSelfNode();
87 }
catch (InterruptedException e) {
99 sMulticastSocket =
new MulticastSocket(PORT);
108 sMulticastSocket.setNetworkInterface(EchoUtils.getNetworkInterface());
110 sMulticastSocket.joinGroup(sMulticastAddress);
111 sMulticastSocket.setLoopbackMode(
true);
112 sMulticastSocket.setSoTimeout(10);
115 sTCPSockets =
new HashMap<String, ArrayList<Socket>>();
117 sServerSocket =
new ServerSocket();
118 sServerSocket.setSoTimeout(10);
119 sServerSocket.setReuseAddress(
true);
120 sServerSocket.bind(
new InetSocketAddress(PORT));
121 sConnectedTCPSocketThreads = Executors.newCachedThreadPool();
126 if(sMulticastSocket != null){
127 MulticastSocket s = sMulticastSocket;
128 sMulticastSocket = null;
129 s.leaveGroup(sMulticastAddress);
132 if(sServerSocket != null){
133 ServerSocket s = sServerSocket;
134 sServerSocket = null;
137 if(sConnectedTCPSocketThreads != null){
138 sConnectedTCPSocketThreads.shutdownNow();
139 sConnectedTCPSocketThreads = null;
141 if(sTCPSockets != null){
142 for(Map.Entry<String,ArrayList<Socket>> entry : sTCPSockets.entrySet()){
143 for(Socket s : entry.getValue()){
154 private static void sendFrameToSelfNode(
EchoFrame frame) {
155 mSelfFrameQueue.offer(frame);
157 private static void receiveFrameFromSelfNode() {
158 EchoFrame frame = mSelfFrameQueue.poll();
160 onReceiveUDPFrame(frame);
164 private static void onReceiveUDPFrame(EchoFrame frame) {
165 checkNewObjectInResponse(frame.copy());
166 Echo.getEventListener().receiveEvent(frame);
168 switch(frame.getESV()) {
169 case EchoFrame.ESV_SETI_SNA:
170 case EchoFrame.ESV_SET_RES:
case EchoFrame.ESV_SETC_SNA:
171 case EchoFrame.ESV_GET_RES:
case EchoFrame.ESV_GET_SNA:
172 case EchoFrame.ESV_INF:
case EchoFrame.ESV_INF_SNA:
173 case EchoFrame.ESV_INFC_RES:
175 onReceiveNotRequest(frame);
177 case EchoFrame.ESV_INFC:
178 onReceiveNotRequest(frame);
179 case EchoFrame.ESV_SETI:
case EchoFrame.ESV_SETC:
180 case EchoFrame.ESV_GET:
181 case EchoFrame.ESV_INF_REQ:
182 case EchoFrame.ESV_SET_GET:
184 EchoNode selfNode = Echo.getSelfNode();
185 if(selfNode == null) {
188 if(frame.getDstEchoInstanceCode() == 0) {
190 EchoObject deoj = selfNode.getNodeProfile();
191 onReceiveUDPRequestFrame(deoj, frame);
193 DeviceObject[] deojList = selfNode.getDevices(frame.getDstEchoClassCode());
194 for(DeviceObject deoj : deojList) {
195 onReceiveUDPRequestFrame(deoj, frame);
199 EchoObject deoj = selfNode.getInstance(frame.getDstEchoClassCode(), frame.getDstEchoInstanceCode());
200 if(deoj == null) {
return;}
201 onReceiveUDPRequestFrame(deoj, frame);
207 private static void onReceiveUDPRequestFrame(EchoObject deoj, EchoFrame frame){
209 EchoFrame request = frame.copy();
210 request.setDstEchoInstanceCode(deoj.getInstanceCode());
211 EchoFrame response = deoj.onReceiveRequest(request);
221 }
catch (IOException e) {
226 private static void onReceiveNotRequest(EchoFrame frame) {
227 EchoNode node = Echo.getNode(frame.getSrcEchoAddress());
228 EchoObject seoj = node.getInstance(frame.getSrcEchoClassCode(),
229 frame.getSrcEchoInstanceCode());
231 if(seoj == null) {
return;}
235 EchoObject.Receiver receiver = seoj.getReceiver();
236 if(receiver != null) {
237 receiver.onReceive(seoj, frame);
242 private static void onReceiveTCPFrame(EchoFrame frame, Socket socket) {
243 checkNewObjectInResponse(frame.copy());
244 Echo.getEventListener().receiveEvent(frame);
245 switch(frame.getESV()) {
246 case EchoFrame.ESV_SETI_SNA:
247 case EchoFrame.ESV_SET_RES:
case EchoFrame.ESV_SETC_SNA:
248 case EchoFrame.ESV_GET_RES:
case EchoFrame.ESV_GET_SNA:
249 case EchoFrame.ESV_INF:
case EchoFrame.ESV_INF_SNA:
250 case EchoFrame.ESV_INFC_RES:
252 onReceiveNotRequest(frame);
254 case EchoFrame.ESV_INFC:
255 onReceiveNotRequest(frame);
256 case EchoFrame.ESV_SETI:
case EchoFrame.ESV_SETC:
257 case EchoFrame.ESV_GET:
258 case EchoFrame.ESV_INF_REQ:
259 case EchoFrame.ESV_SET_GET:
261 EchoNode selfNode = Echo.getSelfNode();
262 if(selfNode == null) {
265 if(frame.getDstEchoInstanceCode() == 0) {
267 EchoObject deoj = selfNode.getNodeProfile();
268 onReceiveTCPRequestFrame(deoj, frame, socket);
270 DeviceObject[] deojList = selfNode.getDevices(frame.getDstEchoClassCode());
271 for(DeviceObject deoj : deojList) {
272 onReceiveTCPRequestFrame(deoj, frame, socket);
276 EchoObject deoj = selfNode.getInstance(frame.getDstEchoClassCode(), frame.getDstEchoInstanceCode());
277 if(deoj == null) {
return;}
278 onReceiveTCPRequestFrame(deoj, frame, socket);
284 private static void onReceiveTCPRequestFrame(EchoObject deoj, EchoFrame frame, Socket socket){
285 EchoFrame request = frame.copy();
286 request.setDstEchoInstanceCode(deoj.getInstanceCode());
287 EchoFrame response = deoj.onReceiveRequest(request);
297 }
catch (IOException e) {
303 private static void checkNewObjectInResponse(EchoFrame frame) {
304 EchoNode node = Echo.getNode(frame.getSrcEchoAddress());
305 boolean flagNewNode =
false;
307 node = Echo.addOtherNode(frame.getSrcEchoAddress());
309 if(node == null) {
return;}
311 node.getNodeProfile().setNode(node);
314 if(frame.getSrcEchoClassCode() == NodeProfile.ECHO_CLASS_CODE
315 && frame.getSrcEchoInstanceCode() == NodeProfile.INSTANCE_CODE_TRANSMISSION_ONLY) {
317 NodeProfile profile = node.getNodeProfile();
318 NodeProfile.Proxy proxy = (NodeProfile.Proxy)profile;
322 boolean flagNewDevice =
false;
323 EchoObject seoj = node.getInstance(frame.getSrcEchoClassCode(), frame.getSrcEchoInstanceCode());
328 seoj = node.addOtherDevice(frame.getSrcEchoClassCode(), frame.getSrcEchoInstanceCode());
329 flagNewDevice =
true;
331 if(seoj != null) {seoj.setNode(node);}
344 if(seoj.getEchoClassCode() == NodeProfile.ECHO_CLASS_CODE
345 && (seoj.getInstanceCode() == NodeProfile.INSTANCE_CODE
347 && (frame.getESV() == EchoFrame.ESV_GET_RES
348 || frame.getESV() == EchoFrame.ESV_GET_SNA
349 || frame.getESV() == EchoFrame.ESV_INF
350 || frame.getESV() == EchoFrame.ESV_INF_SNA
353 List<EchoObject> foundDevices =
new ArrayList<EchoObject>();
354 List<Boolean> flagNewDevices =
new ArrayList<Boolean>();
356 for(EchoProperty p : frame.getPropertyList()) {
357 if(p.epc != NodeProfile.EPC_INSTANCE_LIST_NOTIFICATION
358 && p.epc != NodeProfile.EPC_SELF_NODE_INSTANCE_LIST_S) {
continue;}
359 if(p.pdc == 0) {
continue;}
360 int deviceListSize = (int)p.edt[0];
361 if(deviceListSize > 84) {
364 for(
int d = 0, i = 1; d < deviceListSize; d++) {
365 if(i == p.pdc)
break;
366 short echoClassCode = (short)(((p.edt[i]) & 0xFF) << 8);
368 if(i == p.pdc)
break;
369 echoClassCode += p.edt[i] & 0xFF;
371 if(i == p.pdc)
break;
372 byte echoInstanceCode = p.edt[i];
374 if(node.containsDevice(echoClassCode, echoInstanceCode)) {
375 flagNewDevices.add(
false);
376 foundDevices.add(node.getInstance(echoClassCode, echoInstanceCode));
379 flagNewDevices.add(
true);
380 EchoObject eoj = node.addOtherDevice(echoClassCode, echoInstanceCode);
381 foundDevices.add(eoj);
382 if(eoj != null) {eoj.setNode(node);}
399 int foundDeviceListSize = foundDevices.size();
400 for(
int i = 0; i < foundDeviceListSize; i++) {
401 if(flagNewDevices.get(i)) {
403 foundDevices.get(i).onNew();
406 foundDevices.get(i).onFound();
427 Echo.getEventListener().sendEvent(frame);
430 sendFrameToSelfNode(frame.copy());
433 byte[] data = frame.getFrameByteArray();
435 InetAddress address = InetAddress.getByName(frame.getDstEchoAddress());
436 DatagramPacket packet =
new DatagramPacket(data, data.length,
438 sMulticastSocket.send(packet);
442 sendFrameToSelfNode(f);
447 Echo.getEventListener().sendEvent(frame);
450 sendFrameToSelfNode(frame.copy());
453 InetAddress address = InetAddress.getByName(frame.getDstEchoAddress());
455 if(sTCPSockets.containsKey(frame.getDstEchoAddress())) {
456 ArrayList<Socket> list = sTCPSockets.get(frame.getDstEchoAddress());
458 for(
int i = list.size() - 1; i >= 0; --i) {
459 Socket sock = list.get(i);
464 }
catch(IOException e) {
472 Socket sock =
new Socket(address,PORT);
476 if(sTCPSockets.containsKey(address.getHostAddress())) {
477 sTCPSockets.get(address.getHostAddress()).add(sock);
479 ArrayList<Socket> list =
new ArrayList<Socket>();
481 sTCPSockets.put(address.getHostAddress(), list);
484 sConnectedTCPSocketThreads.execute(
new TCPSocketThread(sock));
488 byte[] data = frame.getFrameByteArray();
489 DataOutputStream out =
new DataOutputStream(socket.getOutputStream());
494 DatagramPacket packet =
499 if(sMulticastSocket == null){
503 sMulticastSocket.receive(packet);
504 Enumeration<InetAddress> enumIpAddr = sMulticastSocket.getNetworkInterface().getInetAddresses();
505 while(enumIpAddr.hasMoreElements()) {
506 InetAddress inetAddress = enumIpAddr.nextElement();
507 if (inetAddress.equals(packet.getAddress())) {
511 byte[] data =
new byte[packet.getLength()];
512 System.arraycopy(packet.getData(), 0, data, 0, packet.getLength());
517 InetAddress address = packet.getAddress();
518 String srcEchoAddress = address.getHostAddress();
520 onReceiveUDPFrame(frame);
525 if(sServerSocket == null){
529 Socket sock = sServerSocket.accept();
530 String address = sock.getInetAddress().getHostAddress();
531 if(sTCPSockets.containsKey(address)) {
532 sTCPSockets.get(address).add(sock);
534 ArrayList<Socket> list =
new ArrayList<Socket>();
536 sTCPSockets.put(address, list);
538 System.err.println(
"Socket add" + sock.getInetAddress() +
"(income)");
540 sConnectedTCPSocketThreads.execute(
new TCPSocketThread(sock));
546 if(sRecvThread == null){
547 sRecvThread =
new Thread(
new Receiver());
557 if(sRecvThread != null){
558 sRecvThread.interrupt();
571 short ret = sNextTID;
582 ArrayList<Socket> list = sTCPSockets.get(socket.getInetAddress().getHostAddress());
586 }
catch (IOException e) {
592 private static class TCPSocketThread
implements Runnable {
594 public TCPSocketThread(Socket s) {
603 DataInputStream in =
new DataInputStream(sock.getInputStream());
604 while (!Thread.interrupted() && sock.isConnected()) {
605 String address = sock.getInetAddress().getHostAddress();
607 EchoFrame frame = EchoFrame.getEchoFrameFromStream(address, in);
610 onReceiveTCPFrame(frame, sock);
612 }
catch (InterruptedException e) {
617 }
catch (IOException e) {
static final String SELF_ADDRESS
static void closeSocket()
static final short ECHO_CLASS_CODE
static final byte ESV_SET_NO_RES
static void sendTCPFrame(EchoFrame frame)
static void resumeReceiverThread()
static final byte ESV_INFC
static void closeTCPSocket(Socket socket)
static void sendUDPFrame(EchoFrame frame)
static final int MIN_FRAME_SIZE
static short getNextTIDNoIncrement()
static final byte ESV_INF
static int UDP_MAX_PACKET_SIZE
static synchronized short nextTID()
static void stopReceiverThread()
static void startReceiverThread()
static int TCP_MAX_PACKET_SIZE
static final byte INSTANCE_CODE_TRANSMISSION_ONLY
static final String MULTICAST_ADDRESS
static void pauseReceiverThread()
static void sendTCPFrame(EchoFrame frame, Socket socket)