Source code: proxy/bearer/http/TalkingWithMobiles.java
1 /**
2 * TODO: destroy some threads if there is much of them (and they are unused)
3 */
4
5 package proxy.bearer.http;
6
7 import java.io.*;
8 import java.net.*;
9 import java.util.*;
10 import proxy.bearer.*;
11 import proxy.protocol.*;
12
13 /**
14 * Multithread proxy server using own data structere for served data.
15 *
16 *
17 */
18 public class TalkingWithMobiles extends Thread implements HttpConstants {
19
20
21 /* print to stdout */
22 protected void p(String s) {
23 System.out.println(s);
24 }
25
26 /**
27 * print to the log file
28 */
29 protected void log(String s) {
30 synchronized (log) {
31 log.println("TWM: " + s);
32 log.flush();
33 }
34 }
35
36 PrintStream log;
37
38 /**
39 * Server's configuration information is stored
40 * in these properties
41 */
42 protected Properties props;
43
44 /**
45 * Where worker threads stand idle
46 */
47 Vector threads;
48
49 /**
50 * the web server's virtual root. Rather not used since serving files where used for testing only.
51 */
52 File root;
53
54 /**
55 * timeout on client connections
56 */
57 int timeout;
58
59 /**
60 * max # worker threads
61 */
62 int workers;
63
64 protected proxy.protocol.ProxyRequestManager myProxyRequestManager;
65
66 private int port;
67
68 /**
69 * here are kept messages which waits for delivery
70 */
71 PreparedMessages myPreparedMessages;
72
73 /**
74 * <p>
75 * Saves given message so it waits for delivery when apropriate client ask for it.
76 * </p><p>
77 * </p><p>
78 * @param code message code according to protocol
79 * </p><p>
80 * @param owner client application identifier
81 * </p><p>
82 * @param id frame identifier
83 * </p><p>
84 * @param mobile client device identifier
85 * </p><p>
86 * @param msg serialized frame body
87 * </p><p>
88 *
89 * </p>
90 */
91 public void putNext(int code, int owner, int id,
92 int mobile, byte[] msg) {
93 log("message id= " + id + " mobile=" + mobile + "owner" + owner +" enqueued for delivery");
94 for (int i = 0; i < msg.length; i++) {
95 System.out.print(msg[i] + " ");
96 }
97 System.out.println();
98
99 myPreparedMessages.put(new ClientIdentifier(mobile, owner),
100 new PreparedMessage(id, code, msg));
101 }
102
103
104 /**
105 * If some message received from one mobile/application was procesed,
106 * this must be acknowledged here.
107 * @param owner client application identifier
108 * @param mobile client device identifier
109 * acknArr array of numbers of properly processed messages
110 */
111 public void putAcknowledge(int owner, int mobile, int[] acknArr){
112 myPreparedMessages.putAcknowledges(new ClientIdentifier(mobile, owner), acknArr);
113 };
114
115
116 /**
117 * Forward message received from mobile to ReqestManager
118 * @param ci message sender identification
119 * @param pm message body with content-type code
120 */
121 public void ForwardFromMobile(ClientIdentifier ci, PreparedMessage pm){
122
123 System.out.println("msg from " + ci.mobile() + ": \"" + new String(pm.msg()) + "\"");
124 synchronized (System.out) {
125 //System.out.println("długość = " + pm.msg().length);
126 for (int i = 0; i < pm.msg().length; i++) {
127 System.out.print(pm.msg()[i] + " ");
128 }
129 System.out.println();
130 for (int i = 0; i < pm.msg().length; i++) {
131 System.out.print( (char) pm.msg()[i] + " ");
132 }
133 System.out.println();
134 }
135
136 //for testing only
137 // myPreparedMessages.put(ci, pm);
138
139 Request req = new Request(pm.code(), ci.owner(), pm.id(), ci.mobile(), pm.msg()) ;
140 myProxyRequestManager.processRequest(req);
141 }
142
143 /**
144 * load configuration file. must be in path pointed by JAVA_HOME enviroment variable.
145 *
146 */
147 void loadProps() throws IOException {
148
149 File f = new File(System.getProperty("user.dir")+File.separator+"proxy-server.conf");
150 if (f.exists()) {
151 InputStream is =new BufferedInputStream(new
152 FileInputStream(f));
153 props.load(is);
154 is.close();
155 String r = props.getProperty("root");
156 if (r != null) {
157 root = new File(r);
158 if (!root.exists()) {
159 throw new Error(root + " doesn't exist as server root - check configuration file");
160 }
161 }
162 r = props.getProperty("timeout");
163 if (r != null) {
164 timeout = Integer.parseInt(r);
165 }
166 r = props.getProperty("workers");
167 if (r != null) {
168 workers = Integer.parseInt(r);
169 }
170 r = props.getProperty("log");
171 if (r != null) {
172 log = new PrintStream(new BufferedOutputStream(
173 new FileOutputStream(r)));
174 }
175 r = props.getProperty("port");
176 if (r != null) {
177 port = Integer.parseInt(r);
178 }
179
180 } else {
181
182 System.err.println("Configuration file not found, should be "+f.getAbsolutePath());
183 throw new Error(root + "configuration file not found");
184 }
185
186 /* if no properties were specified, choose defaults */
187 if (root == null) {
188 root = new File(System.getProperty("user.dir"));
189 }
190 if (timeout <= 1000) {
191 timeout = 5000;
192 }
193 if (workers < 25) {
194 workers = 5;
195 }
196 if (log == null) {
197 // p("logging to stdout");
198 log = System.out;
199 }
200 }
201
202 /**
203 * print Properties servers was ran with.
204 */
205 void printProps() {
206 p("root=" + root + ", timeout=" + timeout + ", workers=" + workers +
207 ", log=" + log + ", port = " + port);
208 }
209
210 public void setProxyRequestManager(ProxyRequestManager prm){
211 this.myProxyRequestManager = prm;
212 }
213
214 public void run() {
215 /* start worker threads */
216 try {
217 for (int i = 0; i < workers; ++i) {
218
219 Worker w = new Worker(myProxyRequestManager, log, myPreparedMessages, threads);
220 (new Thread(w, "worker #" + i)).start();
221 threads.addElement(w);
222 }
223
224 ServerSocket ss = new ServerSocket(this.port);
225
226 while (true) {
227 Socket s = ss.accept();
228
229 Worker w = null;
230 synchronized (threads) {
231 if (threads.isEmpty()) {
232 Worker ws = new Worker(myProxyRequestManager, log, myPreparedMessages, threads);
233 ws.setSocket(s);
234 (new Thread(ws, "additional worker")).start();
235 }
236 else {
237 w = (Worker) threads.elementAt(0);
238 threads.removeElementAt(0);
239 w.setSocket(s);
240 }
241 }
242 }
243 }
244 catch (IOException err) {
245 log("cought exc"+err.getMessage());
246 }
247
248 }
249
250 // /**
251 // * dummy constructor
252 // */
253 // public TalkingWithMobiles(){
254 // }
255
256 protected TalkingWithMobiles()
257 {
258
259 }
260 /**
261 * proper constructor
262 */
263 public TalkingWithMobiles(ProxyRequestManager _prm){
264
265 threads = new Vector();
266 myPreparedMessages = new PreparedMessages();
267 props = new Properties();
268 workers = 3;
269 timeout = 0;
270 port = 8080;
271 myProxyRequestManager = _prm;
272 try
273 {
274 loadProps();
275 }
276 catch (IOException err)
277 {
278 log("No configuration file found");
279 }
280 printProps();
281 }
282
283 /**
284 * run me.
285 */
286 public static void main(String[] a) throws Exception {
287
288 }
289 }