Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: marauroa/net/NetworkClientManager.java


1   /* $Id: NetworkClientManager.java,v 1.9 2003/12/08 23:40:10 arianne_rpg Exp $ */
2   /***************************************************************************
3    *                      (C) Copyright 2003 - Marauroa                      *
4    ***************************************************************************
5    ***************************************************************************
6    *                                                                         *
7    *   This program is free software; you can redistribute it and/or modify  *
8    *   it under the terms of the GNU General Public License as published by  *
9    *   the Free Software Foundation; either version 2 of the License, or     *
10   *   (at your option) any later version.                                   *
11   *                                                                         *
12   ***************************************************************************/
13  package marauroa.net;
14  
15  import java.net.*;
16  import java.util.*;
17  import java.io.*;
18  import marauroa.*;
19  
20  /** The NetworkClientManager is in charge of sending and recieving the packages 
21   *  from the network. */
22  public class NetworkClientManager
23    {
24    private DatagramSocket socket;
25    private InetSocketAddress address;
26    private int clientid;
27    
28    private MessageFactory msgFactory;
29    
30    static private class PacketContainer
31      {
32      public byte signature;
33      public byte remaining;
34      public byte[] content;
35      public InetSocketAddress address;    
36      public Date timestamp;
37      }    
38    
39    private Map pendingPackets;
40  
41    /** Constructor that opens the socket on the marauroa_PORT and start the thread
42        to recieve new messages from the network. */
43    public NetworkClientManager(String host) throws SocketException
44      {
45      clientid=0;
46      address=new InetSocketAddress(host,NetConst.marauroa_PORT);
47      socket=new DatagramSocket();
48      socket.setSoTimeout(TimeoutConf.SOCKET_TIMEOUT);
49      
50      msgFactory=MessageFactory.getFactory();
51      pendingPackets=new HashMap();
52      }
53    
54    /** This method notify the thread to finish it execution */
55    public void finish()
56      {
57      socket.close();
58      }
59      
60    /** This method returns a message if it is available or null
61     *  @return a Message*/
62    public Message getMessage()
63      {
64      try
65        {          
66        Iterator it=pendingPackets.entrySet().iterator();
67        while(it.hasNext())
68          {
69          Map.Entry entry=(Map.Entry)it.next();
70          PacketContainer message=(PacketContainer)entry.getValue();
71          if(message.remaining==0)
72            {
73            Message msg=msgFactory.getMessage(message.content,message.address);      
74            System.out.println("NetworkClientManager: receive message("+msg.getType()+") from "+msg.getClientID());
75        
76            if(msg.getType()==Message.TYPE_S2C_LOGIN_ACK)
77              {
78              clientid=msg.getClientID();        
79              }
80                
81            pendingPackets.remove(new Byte(message.signature));
82            return msg;
83            }
84          
85          if(new Date().getTime()-message.timestamp.getTime()>TimeoutConf.CLIENT_MESSAGE_DROPPED_TIMEOUT)
86            {
87            System.out.println("NetworkClientManager: deleted incompleted message after timedout");
88            pendingPackets.remove(new Byte(message.signature));
89            }
90          }
91        }
92      catch(IOException e)
93        {
94        /* Report the exception */
95        marauroad.report(e.getMessage());
96        return null;
97        }
98  
99      byte[] buffer=new byte[NetConst.UDP_PACKET_SIZE];
100     DatagramPacket packet=new DatagramPacket(buffer,buffer.length);
101     int i=0;
102     
103     try
104       {
105       /** We want to avoid this to block the whole client recieving messages */
106       while(i<TimeoutConf.CLIENT_NETWORK_NUM_READ)
107         {
108         ++i;
109         
110         socket.receive(packet);          
111         byte[] data=packet.getData();
112       
113         /* A multipart message. We try to read the rest now. 
114          * We need to check on the list if the message exist and it exist we add this one. */
115        /* TODO: Looks like hardcoded, write it in a better way */
116         byte total=data[0];
117         byte position=data[1];
118         byte signature=data[2];
119         System.out.println("NetworkClientManager: receive multipart message("+signature+"): "+(position+1)+" of "+total);
120 
121         if(!pendingPackets.containsKey(new Byte(signature)))
122           {
123           /** This is the first packet */
124           PacketContainer message=new PacketContainer();
125           message.signature=signature;
126           message.remaining=(byte)(total-1);
127           message.address=(InetSocketAddress)packet.getSocketAddress();
128           message.content=new byte[(NetConst.UDP_PACKET_SIZE-3)*total];
129           message.timestamp=new Date();
130           
131           System.arraycopy(data,3,message.content,(NetConst.UDP_PACKET_SIZE-3)*position,data.length-3);      
132           pendingPackets.put(new Byte(signature),message);
133           }
134         else
135           {
136           PacketContainer message=(PacketContainer)pendingPackets.get(new Byte(signature));
137           --message.remaining;
138           
139           if(message.remaining<0)
140             {
141             System.out.println("ERROR: We confused the messages");
142             return null;
143             }
144 
145           System.arraycopy(data,3,message.content,(NetConst.UDP_PACKET_SIZE-3)*position,data.length-3);      
146           }
147         }
148         
149       return null;        
150       }
151     catch(java.net.SocketTimeoutException e)
152       {
153       /* We need the thread to check from time to time if user has requested an exit */
154       return null;        
155       }
156     catch(IOException e)
157       {
158       /* Report the exception */
159       marauroad.report(e.getMessage());
160       return null;
161       }
162     }
163     
164   /** This method add a message to be delivered to the client the message is pointed to.
165    *  @param msg the message to ve delivered. */
166   public synchronized void addMessage(Message msg)
167     {
168     try
169       {
170       /* We enforce the remote endpoint */
171       msg.setAddress(address);
172       msg.setClientID(clientid);
173       
174       ByteArrayOutputStream out=new ByteArrayOutputStream();
175       OutputSerializer s=new OutputSerializer(out);
176  
177       System.out.println("NetworkClientManager: send message("+msg.getType()+") from "+msg.getClientID());
178       s.write(msg);
179    
180       byte[] buffer=out.toByteArray();
181       DatagramPacket pkt=new DatagramPacket(buffer,buffer.length,msg.getAddress());
182      
183       socket.send(pkt);
184       }
185     catch(IOException e)
186       {    
187       /* Report the exception */
188       marauroad.report(e.getMessage());
189       }
190     }       
191   }