aboutsummaryrefslogtreecommitdiff
path: root/src/Puppet.java
blob: 17844ea3b2a60ee97b41dc2cce1351d2fe7f030a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
 * Part of a Ivy-level proxy
 *
 * @author	Yannick Jestin
 * @author	<a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
 *
 * (c) CENA 1998-2004
 *
 *  CHANGELOG:
 *  1.2.14
  *   - switch from gnu regexp (deprecated) to the built in java regexp
 *    - add generic types to declarations
 *  1.2.13:
 *    - adds support for RESyntaxException
 */

package fr.dgac.ivy ;
import java.lang.Thread;
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;

class Puppet {

  // the mapping between Ghost regexp and local bus regexp numbers
  Hashtable<String,String> bound = new Hashtable<String,String>(); // ghostID localID
  Hashtable<String,String>regexps = new Hashtable<String,String>(); // ghostID textRegexp
  String domain;
  String appName;
  ProxyClient pc;
  String id;
  boolean started;
  PuppetIvy bus;

  Puppet(ProxyClient pc,String id,String domain) {
    this.domain=domain;
    this.pc=pc;
    this.id=id;
  }

  void sendGhost(String s) { pc.send("ForwardGhost id="+id+" buffer="+s); }

  class ForwardMessenger implements IvyMessageListener {
    String localId,ghostId;
    public ForwardMessenger(String ghostId,String re) throws IvyException {
      this.ghostId=ghostId;
      this.localId = Integer.valueOf(bus.bindMsg(re,ForwardMessenger.this)).toString();
      bound.put(ghostId,localId);
    }
    public void receive(IvyClient ic,String args[]) {
      StringBuffer tosend = new StringBuffer(IvyClient.Msg);
      tosend.append(" ");
      tosend.append(ghostId);
      tosend.append(IvyClient.StartArg);
      for (int i=0;i<args.length;i++) {
	tosend.append(args[i]);
	tosend.append(IvyClient.EndArg);
      }
      sendGhost(tosend.toString());
    }
  } // ForwardMessenger

  void addRegexp(String ghostId,String re) {
    regexps.put(ghostId,re);
    try {
      if (started) new ForwardMessenger(ghostId,re);
    } catch( IvyException ie) { ie.printStackTrace(); }
  }

  void removeRegexp(String ghostId) {
    try {
      bus.unBindMsg(Integer.parseInt((String)bound.remove(ghostId)));
    } catch( IvyException ie) { ie.printStackTrace(); }
  }

  void stop() {
    if (started) bus.stop();
  }

  // ivy forwarded protocol message
  static Pattern ivyProto;

  static {
    try {
      ivyProto = Pattern.compile("(\\d+) (\\d+)\\02(.*)");
    } catch (PatternSyntaxException res ) {
      res.printStackTrace();
      System.out.println("Regular Expression bug in Ivy source code ... bailing out");
      System.exit(0);
    }
  }

  void parse(String s) throws IvyException {
    Matcher m;
    if (!(m=ivyProto.matcher(s)).matches()) { System.out.println("Puppet error, can't parse "+s); return; } 
    int pcode=Integer.parseInt(m.group(1));
    String pid=m.group(2);
    String args=m.group(3);
    trace("must parse code:"+pcode+" id:"+pid+" args:"+args);
    switch (pcode) {
      case IvyClient.AddRegexp: // the Ghost's peer subscribes to something
	addRegexp(pid,args);
      	break;
      case IvyClient.DelRegexp: // the Ghost's peer unsubscribes to something
	removeRegexp(pid);
        break;
      case IvyClient.Bye:	// the Ghost's peer disconnects gracefully
      	bus.stop();
	// TODO end of the puppet ?
      	break;
      case IvyClient.Die:
      	// the Ghost's peer wants to ... kill ProxyClient ?
      	break;
      case IvyClient.Msg:
      	// the Ghost's peer sends a message to ProxyClient, with regard to one
	// of our subscriptions
	// TODO a qui le faire passer ?
      	break;
      case IvyClient.SchizoToken:
      	appName = args;
	bus = new PuppetIvy(appName,appName+" fakeready",null);
	for ( String ghostId: regexps.keySet() )new ForwardMessenger(ghostId,regexps.get(ghostId));
	started=true;
	trace("starting the bus on "+domain);
	bus.start(domain);
        break;
      case IvyClient.Error:
      case IvyClient.EndRegexp:
      case IvyClient.DirectMsg:
      case IvyClient.Ping:
      case IvyClient.Pong:
      default:
    	trace("unused Ivy protocol code "+pcode);
    }
  }

  static class PuppetIvy extends Ivy {
    PuppetIvy(String name,String ready,IvyApplicationListener ial){super(name,ready,ial);}
    protected IvyClient createIvyClient(Socket s,int port, boolean domachin) throws IOException {
      return new PuppetIvyClient(PuppetIvy.this,s,port,domachin);
    }
    int getAP() {return getAppPort();}
  }

  static class PuppetIvyClient extends IvyClient {
    PuppetIvyClient(Ivy bus,Socket s,int port,boolean b) throws IOException  { super(bus,s,port,b); }
    protected synchronized void sendBuffer( String s ) throws IvyException {
      super.sendBuffer(s); // and to all the agents on the Ghost bus ? I'm not sure
    }
    protected boolean newParseMsg(String s) throws IvyException {
      return super.newParseMsg(s); // I'm a normal Ivy citizen
    }
  }

  void trace(String s) { System.out.println("Puppet["+id+"] "+s);}

}