root/as3/OSCemote/branches/saqoosha/server/flosc-0.3.1/TcpServer.java

リビジョン 1048, 6.8 kB (コミッタ: uranodai, コミット時期: 4 年 前)

--

Line 
1 import java.awt.event.*;
2 import java.util.*;
3 import java.awt.*;
4 import java.io.*;
5 import java.net.*;
6
7 /**
8  *
9  * TcpServer
10  * <BR><BR>
11  * Flash XML Socket Server for Gateway.
12  *
13  * Based on CommServer by Derek Clayton.
14  *
15  *
16  * @author  Ben Chun        ben@benchun.net
17  * @version 1.0
18  */
19
20 public class TcpServer extends Thread {
21     private Vector clients = new Vector();  // all connected Flash clients
22     private int port;                       // the TCP port
23     ServerSocket server;                    // the TCP server
24     Gateway gateway;                        // Gateway for this server
25    
26     /**
27      * Constructor for the TcpServer.
28      * @param   port   TCP port for Flash client connections.
29      * @param   gateway  parent Gateway.
30     */
31     public TcpServer(int port, Gateway gateway) {
32         this.port = port;
33         this.gateway = gateway;
34         System.out.println("TcpServer created...");
35     }
36
37
38     /**
39      * Thread run method.  Monitors incoming messages.
40     */ 
41     public void run() {
42         try {
43             // --- create a new TCP server
44             server = new ServerSocket(port);
45             Debug.writeActivity("TCP XML/Flash server started on port: " + port);
46             // --- while the server is active...
47             while(true) {
48                 // --- ...listen for new client connections
49                 Socket socket = server.accept();
50                 TcpClient client = new TcpClient(this, socket);
51                 Debug.writeActivity(client.getIP()+ " connected to TCP XML/Flash server.");
52                 // --- add the new client to our client list
53                 clients.addElement(client);
54                 // --- start the client thread
55                 client.start();
56             }
57         } catch(IOException ioe) {
58             Debug.writeActivity("Server error...Stopping TCP XML/Flash server");
59             // kill this server
60             killServer();
61         }
62     }
63
64     /**
65      * Broadcasts a message to all connected Flash clients.
66      * Messages are terminated with a null character.
67      *
68      * @param   message    The message to broadcast.
69     */
70     public synchronized void broadcastMessage(String message) {
71         // --- add the null character to the message
72         message += '\0';
73        
74         // --- enumerate through the clients and send each the message
75         Enumeration enum = clients.elements();
76         while (enum.hasMoreElements()) {
77             TcpClient client = (TcpClient)enum.nextElement();
78             client.send(message);
79         }
80     }
81
82     /**
83      * Takes incoming XML-encoded OSC and creates an OSC packet for
84      * the Gateway to send.  This pseduo-parser method does not
85      * validate the XML in any way, so client applications should take
86      * care to send only well-formed XMl that would validate against
87      * flosc.dtd (usually this is not a problem, since flosc.fla does
88      * it correctly).
89      *
90      * @param   client    The TcpClient to remove.
91      *
92      */
93     public void handleOsc(String oscxml) throws UnknownHostException {
94         Debug.writeActivity("Received TCP packet, parsing XML...");
95
96         // DEBUG
97         //Debug.writeActivity(oscxml);
98
99         //  parse the XML, create an OscPacket
100         StringTokenizer st = new StringTokenizer(oscxml, " =<>\"", false);
101         OscPacket packet = new OscPacket();
102
103         // this gets ugly, i know.  it was this or a real xml parser.
104         boolean validOSC = false;
105         boolean inMessage = false;
106         OscMessage message = new OscMessage("/ERROR");
107         while (st.hasMoreTokens() ) {
108             String token = st.nextToken();
109             if (token.compareTo("OSCPACKET") == 0)
110                 validOSC = true;
111             if (token.compareTo("TIME") == 0)
112                 packet.setTime( Long.parseLong(st.nextToken()) );
113             if (token.compareTo("ADDRESS") == 0)
114                 packet.setAddress( InetAddress.getByName(st.nextToken()) );
115             if (token.compareTo("PORT") == 0)
116                 packet.setPort( Integer.parseInt(st.nextToken()) );
117
118             if (token.compareTo("MESSAGE") == 0) {
119                 inMessage = true;
120                 token = st.nextToken();
121             }
122
123             if (inMessage) {
124                 if(token.compareTo("NAME")  == 0)
125                     message = new OscMessage( st.nextToken() );
126                
127                 // TBD : change DTD to be <ARG TYPE="x">value
128                 // here</ARG>
129            
130                 // danger : relies on ARGUMENT attributes to occur in
131                 // order TYPE, VALUE
132                
133                 if (token.compareTo("ARGUMENT") == 0) {
134                     token = st.nextToken();
135                     char tchar = 'i';
136                     if (token.compareTo("TYPE") == 0) {
137                         tchar = st.nextToken().charAt(0);
138                         token = st.nextToken();
139                     }
140                     Character type = new Character(tchar);
141
142                     if (token.compareTo("VALUE") == 0) {
143                         String value = st.nextToken();
144                         switch (tchar) {
145                         case 'i': case 'r': case 'm': case 'c':
146                             Integer i = Integer.valueOf( value );
147                             message.addArg(type, i);
148                             break;
149                         case 'f':
150                             Float f = Float.valueOf( value );
151                             message.addArg(type, f);
152                             break;
153                         case 'h': case 't':
154                             Long l = Long.valueOf( value );
155                             message.addArg(type, l);
156                             break;
157                         case 'd':
158                             Double d = Double.valueOf( value );
159                             message.addArg(type, d);
160                             break;
161                         case 's': case 'S':
162                             message.addArg(type, unescape(value));
163                             break;
164                         }
165                     }
166                 }
167             }
168
169             if (token.compareTo("/MESSAGE") == 0) {
170                 packet.addMessage(message);
171                 inMessage = false;
172             }
173
174             if (!validOSC)
175                 Debug.writeActivity("Parse error: data outside OSCPACKET element");
176         }
177        
178         gateway.sendPacket(packet);
179     }
180
181
182     /**
183      * Replaces escape codes in a string with the literal
184      * characters. (e.g.: "%20" is replaced with a space).
185      *
186      * (c) 2001 by Phil Scovis, all rights reserved.  This code is
187      * provided as-is, without warranty.  You may copy, use, or
188      * distribute this code, provided that you add value to it and
189      * include this notice.
190      *
191      * @param s the string with escape codes.
192      * @return the string with the escape codes replaced.
193      */
194     public String unescape(String s){
195         String retval="";
196         for (int i=0; i<s.length(); i++){
197             switch(s.charAt(i)){
198             case '%':
199                 String hexCode = s.substring(i+1, i+3);
200                 int hexValue = Integer.parseInt(hexCode,16);
201                 retval+=(char)hexValue;
202                 i+=2;
203                 break;
204             default:           
205                 retval+=s.charAt(i);
206             }
207         }
208         return retval;
209     }
210    
211    
212
213
214     /**
215      * Removes clients from the client list.
216      *
217      * @param   client    The TcpClient to remove.
218      *
219     */
220     public void removeClient(TcpClient client) {
221         Debug.writeActivity(client.getIP() + " has disconnected from the server.");
222        
223         // --- remove the client from the list
224         clients.removeElement(client);
225        
226     }
227
228     /**
229      * Stops the TCP server.
230     */
231     public void killServer() {
232         try {
233             // --- stop the server
234             server.close();
235             Debug.writeActivity("TCP XML/Flash server stopped");
236         } catch (IOException ioe) {
237             Debug.writeActivity("Error while stopping TCP XML/Flash server");
238         }
239     }
240 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。