View Javadoc

1   /*
2    * Copyright (c) 2014. Peter Crossley (xley.com)
3    *  Licensed to the Apache Software Foundation (ASF) under one
4    *  or more contributor license agreements.  See the NOTICE file
5    *  distributed with this work for additional information
6    *  regarding copyright ownership.  The ASF licenses this file
7    *  to you under the Apache License, Version 2.0 (the
8    *  "License"); you may not use this file except in compliance
9    *  with the License.  You may obtain a copy of the License at
10   *
11   *    http://www.apache.org/licenses/LICENSE-2.0
12   *
13   *  Unless required by applicable law or agreed to in writing,
14   *  software distributed under the License is distributed on an
15   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   *  KIND, either express or implied.  See the License for the
17   *  specific language governing permissions and limitations
18   *  under the License.
19   */
20  
21  package com.xley.lfosc;
22  
23  import com.illposed.osc.OSCPortIn;
24  import com.xley.lfosc.impl.LightFactoryProxyThread;
25  import com.xley.lfosc.impl.OSCProxyListener;
26  import com.xley.lfosc.util.LogUtil;
27  import joptsimple.OptionSet;
28  
29  import java.io.IOException;
30  import java.net.*;
31  import java.text.MessageFormat;
32  import java.util.Locale;
33  import java.util.ResourceBundle;
34  
35  /**
36   * The type Proxy daemon.
37   */
38  public class ProxyDaemon implements Runnable {
39  
40      /**
41       * The constant resources.
42       */
43      public static final ResourceBundle resources = ResourceBundle.getBundle(ProxyDaemon.class.getSimpleName(),
44              Locale.getDefault());
45      private final Object monitor = true;
46  
47      //configuration
48      private final OptionSet options;
49      OSCProxyListener listener = new OSCProxyListener();
50      //daemon vars
51      private Boolean shutdown = false;
52      private Thread runner;
53      private int errorcode = 0;
54      //connections
55      private ServerSocket serverSocket;
56      private OSCPortIn receiver = null;
57  
58  
59      /**
60       * Instantiates a new Proxy daemon.
61       *
62       * @param optionSet the options from the command line
63       */
64      protected ProxyDaemon(final OptionSet optionSet) {
65          this.options = optionSet;
66      }
67  
68      /**
69       * Get the current error code.
70       *
71       * @return the error code
72       */
73      public final int errorcode() {
74          return this.errorcode;
75      }
76  
77      /**
78       * Shutdown the OSC proxy.
79       */
80      public final void shutdown() {
81          synchronized (monitor) {
82              if (shutdown) {
83                  return;
84              }
85          }
86          shutdown = true;
87          LogUtil.info(this.getClass(), resources.getString("shutdown.inprogress"));
88          runner.interrupt();
89          if (receiver != null) {
90              receiver.stopListening();
91              receiver.close();
92          }
93  
94          if (listener != null) {
95              listener.shutdown();
96          }
97  
98          if (serverSocket != null) {
99              try {
100                 serverSocket.close();
101                 serverSocket = null;
102             } catch (Throwable e) {
103                 LogUtil.trace(e);
104             }
105         }
106     }
107 
108     @Override
109     public final void run() {
110         runner = Thread.currentThread();
111 
112         int portNumber = (int) options.valueOf("p");
113         int oscPortNumber = (int) options.valueOf("l");
114         int threads = (int) options.valueOf("t");
115         boolean oscEnabled = true;
116         boolean lfBridgeEnabled = true;
117 
118         switch (String.valueOf(options.valueOf("m"))) {
119             case "osc":
120                 oscEnabled = true;
121                 lfBridgeEnabled = false;
122                 break;
123             case "bridge":
124                 oscEnabled = false;
125                 lfBridgeEnabled = true;
126                 break;
127             case "both":
128                 break;
129             default:
130                 LogUtil.error(this.getClass(), resources.getString("options.mode.invalid"));
131                 errorcode = 1;
132                 shutdown();
133                 return;
134         }
135 
136         String host = String.valueOf(options.valueOf("b"));
137         try {
138             //bindings
139             InetSocketAddress binding = new InetSocketAddress(InetAddress.getByName(host), portNumber);
140             InetSocketAddress oscBinding = new InetSocketAddress(InetAddress.getByName(host), oscPortNumber);
141 
142             if (oscEnabled) {
143                 LogUtil.info(this.getClass(), MessageFormat.format(resources.getString("osc.listener.on"), host, oscPortNumber));
144                 receiver = new OSCPortIn(new DatagramSocket(oscBinding));
145                 receiver.addListener(resources.getString("osc.listener.binding"), listener);
146                 receiver.startListening();
147 
148                 //check to see if we are the only listener to run.
149                 if (!lfBridgeEnabled) {
150                     while (!shutdown) {
151                         if (!receiver.isListening() || Thread.currentThread().isInterrupted()) {
152                             break;
153                         }
154                     }
155                 }
156 
157             }
158             if (lfBridgeEnabled) {
159                 try {
160                     serverSocket = new ServerSocket(binding.getPort(), threads, binding.getAddress());
161                     LogUtil.info(this.getClass(), MessageFormat.format(resources.getString("lf.listener.on"), host, portNumber));
162                     while (!shutdown && !Thread.currentThread().isInterrupted()) {
163                         new LightFactoryProxyThread(serverSocket.accept()).start();
164                     }
165                 } catch (IOException e) {
166                     if (!shutdown) {
167                         LogUtil.fatal(this.getClass(), MessageFormat.format(resources.getString("lf.listener.on.error"),
168                                 host, portNumber), e);
169                         errorcode = 2;
170                     }
171                 }
172             }
173 
174         } catch (UnknownHostException e) {
175             LogUtil.fatal(this.getClass(), MessageFormat.format(resources.getString("daemon.error.unknown.host"), host), e);
176             errorcode = 2;
177         } catch (SocketException e) {
178             LogUtil.fatal(this.getClass(), MessageFormat.format(resources.getString("daemon.error.socket"), host), e);
179             LogUtil.fatal(this.getClass(), "", e);
180             errorcode = 2;
181         } finally {
182             shutdown();
183         }
184     }
185 }