1 /**
2 * AUTOHIT 2003
3 * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Additional license information can be found in the documentation.
19 * @author Erich P Gatejen
20 */
21 package autohit.server.service;
22
23 import java.net.ServerSocket;
24 import java.net.Socket;
25 import java.net.SocketTimeoutException;
26 import java.util.HashSet;
27 import java.util.Iterator;
28
29 import autohit.common.AutohitErrorCodes;
30 import autohit.common.AutohitProperties;
31 import autohit.common.Utils;
32
33 /**
34 * This is a socket relay service. It's a dumb relay for sockets. Don't ask why
35 * I did this. It will accept connections on port
36 * AutohitProperties.value_SOCKETRELAY_SERVER_PORT. It'll relay them to the
37 * current property settings for
38 * AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_ADDR and
39 * AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_PORT for address and port,
40 * respectively. If either is not set, a default will be used, though there is
41 * little utility in the default.
42 * <p>
43 * <p>
44 * The relay will stay active until either side drops the connection. There is
45 * absolutely no filtering or logging.
46 *
47 * @author Erich P. Gatejen
48 * @version 1.0 <i>Version History</i><code>EPG - Initial - 12SEP03</code>
49 */
50 public class SocketRelayService extends Service {
51
52 final private static int ACCEPT_TIMEOUT = 1000;
53 final private static int CLEANUP_THRESHOLD = 200;
54
55 /**
56 * accept port */
57 ServerSocket listen;
58
59 /**
60 * active ports */
61 HashSet active;
62
63 /**
64 * Default constructor */
65 public SocketRelayService() {
66 super();
67 }
68
69 /**
70 * Complete construction. This will be called when the VM is initialized. */
71 public void construct() throws ServiceException {
72
73 try {
74
75 // How are we confiugred
76 int port = AutohitProperties.default_SOCKETRELAY_SERVER_PORT;
77 String portString =
78 (String) Utils.testGetProperty(
79 AutohitProperties.SERVICE_SOCKETRELAY_SERVER_PORT,
80 sc.getPropertiesSet());
81 if (portString != null) {
82 port = Integer.parseInt(portString);
83 }
84
85 // Set up communication
86 listen = new ServerSocket(port);
87 active = new HashSet();
88
89 } catch (NumberFormatException nee) {
90 throw new ServiceException(
91 "Failed constructing HttpCommandService. Bad value for property " +
92 AutohitProperties.SERVICE_SOCKETRELAY_SERVER_PORT + ". message=" + nee.getMessage(),
93 ServiceException.CODE_SERVICE_STARTUP_FAULT);
94
95 } catch (Exception ee) {
96 throw new ServiceException(
97 "Failed constructing SocketRelayService. message=" + ee.getMessage(),
98 ServiceException.CODE_SERVICE_STARTUP_FAULT);
99 }
100
101 }
102
103 /**
104 * Fast loop. We spend most of our time waiting for connections. Cycle back
105 * to VM only after an accept or a timeout.
106 *
107 * @see autohit.vm.VMException
108 */
109 public void execute() throws ServiceException {
110
111 Socket accepted;
112 int dport;
113 String daddress;
114 boolean wirelogging;
115
116 // Try to accept
117 try {
118
119 // Do we need to clean the active set?
120 if (active.size() > CLEANUP_THRESHOLD) {
121 this.cleanActive();
122 }
123
124 // ACCEPT
125 listen.setSoTimeout(ACCEPT_TIMEOUT);
126 accepted = listen.accept();
127 myLog.debug("SocketRelayService:Accepted a connection.", AutohitErrorCodes.CODE_DEBUGGING_SERVICES);
128
129 // BUILD HELPER
130 daddress =
131 (String) Utils.testGetProperty(
132 AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_PORT,
133 sc.getPropertiesSet());
134 if (daddress == null) {
135 dport = AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_PORT_default;
136 } else {
137 dport = Integer.parseInt(daddress);
138 }
139 daddress =
140 (String) Utils.testGetProperty(
141 AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_ADDR,
142 sc.getPropertiesSet());
143 if (daddress == null)
144 daddress = AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_ADDR_default;
145
146 // Do we want to capture wire logging?
147 wirelogging =
148 Utils.testGetPropertyTruth(AutohitProperties.SERVICE_SOCKETRELAY_WIRELOGGING, sc.getPropertiesSet());
149
150 // Build helper
151 SocketRelayHelper srh = new SocketRelayHelper();
152 srh.init(accepted, daddress, dport, myLog, wirelogging);
153 myLog.debug(
154 "SocketRelayService:Relay helper initialized. destination=" + daddress + ":" + dport,
155 AutohitErrorCodes.CODE_DEBUGGING_SERVICES);
156
157 // dispatch
158 srh.start();
159 active.add(srh);
160 myLog.debug("SocketRelayService:Relay helper dispatched.", AutohitErrorCodes.CODE_DEBUGGING_SERVICES);
161
162 } catch (NumberFormatException ste) {
163 throw new ServiceException(
164 "Fault in SocketRelayService. "
165 + AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_PORT
166 + " is not a parsable integer.",
167 ServiceException.CODE_SERVICE_GENERAL_FAULT);
168
169 } catch (SocketTimeoutException ste) {
170 // This is ok. Ignore and move on
171
172 } catch (Exception ee) {
173 throw new ServiceException(
174 "Fault in SocketRelayService. message=" + ee.getMessage(),
175 ServiceException.CODE_SERVICE_GENERAL_FAULT);
176 }
177 }
178
179 /**
180 * Helper */
181 private void cleanActive() throws Exception {
182
183 Iterator i = active.iterator();
184
185 while (i.hasNext()) {
186 SocketRelayHelper srh = (SocketRelayHelper) i.next();
187 if (!srh.isAlive())
188 active.remove(srh);
189 }
190 }
191
192 /**
193 * Complete destroy. This will be called when the VM is finalizing. */
194 public void destruct() throws ServiceException {
195
196 Iterator i = active.iterator();
197
198 while (i.hasNext()) {
199 SocketRelayHelper srh = (SocketRelayHelper) i.next();
200 active.remove(srh);
201 if (srh.isAlive()) {
202 try {
203 srh.interrupt();
204 } catch (Exception eee) { // dont care
205 }
206 }
207 } // end while
208
209 } // end destruct
210
211 }
|