source: Evidence/Bridge.cc@ 226

Last change on this file since 226 was 224, checked in by ogrimm, 14 years ago
Message severity encoded now using standard DIM structure, other updates
File size: 5.5 KB
Line 
1/********************************************************************\
2
3 Bridge between two networks
4
5 Subscription to top-level server list DIS_DNS/SERVER_LIST not via
6 AddService() ensures AddService() only called from infoHandler(),
7 thus serialized by DIM and no Mutex is necessary.
8
9 Remote procedure calls are bridged through their underlying services
10 and commands.
11
12 Oliver Grimm, June 2010
13
14\********************************************************************/
15
16#define SERVER_NAME "Bridge"
17#include "Evidence.h"
18
19#include <string>
20#include <vector>
21
22const int DEFAULT_PORT = 2505;
23
24using namespace std;
25
26
27// Class declaration
28class Bridge: public DimClient, public EvidenceServer {
29
30 struct Item {
31 string Name;
32 DimCommand *Command;
33 DimStampedInfo *DataItem;
34 DimService *Service;
35 char *Data;
36 };
37 vector<struct Item> List;
38
39 DimInfo *ServerList;
40
41 void infoHandler();
42 void commandHandler();
43 void AddService(string, char *, int);
44 void RemoveService(string);
45
46 public:
47 Bridge(char *, int);
48 ~Bridge();
49};
50
51// Constructor
52Bridge::Bridge(char *Name, int Port): EvidenceServer(SERVER_NAME) {
53
54 // Set primary DIM network to subscribe from
55 DimClient::setDnsNode(Name, Port);
56
57 // Subsribe to top-level server list
58 ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
59}
60
61
62// Destructor: Delete all subscriptions and services
63Bridge::~Bridge() {
64
65 while (List.size() != 0) RemoveService(List[0].Name);
66 delete ServerList;
67}
68
69
70// Service subscription and repeating
71void Bridge::infoHandler() {
72
73 DimInfo *I = getInfo();
74
75 // Check if service available
76 if (!ServiceOK(I)) return;
77
78 // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services
79 if (strcmp(I->getName(), "DIS_DNS/SERVER_LIST") == 0) {
80 char *Token = strtok(I->getString(), "+-!@");
81 while (Token != NULL) {
82 if (*I->getString() == '-' || *I->getString() == '!') {
83 RemoveService(string(Token)+"/SERVICE_LIST");
84 }
85 else AddService(string(Token)+"/SERVICE_LIST", (char *) "C", DimSERVICE);
86
87 // Skip server IP address and process ID
88 Token = strtok(NULL, "|");
89 Token = strtok(NULL, "@");
90 }
91 return;
92 }
93
94 // If service is SERVICE_LIST, scan and subscribe/unsubscribe to services
95 if (strstr(I->getName(), "/SERVICE_LIST") != NULL) {
96 char *Format, *Name = strtok(I->getString(), "+-!|");
97 while (Name != NULL) {
98 if ((Format = strtok(NULL, "\n")) != NULL) {
99 // Check if service added or removed/unavailable
100 if (*I->getString() == '-' || *I->getString() == '!') {
101 if (strstr(Format, "|RPC") != NULL) {
102 RemoveService(string(Name)+"/RpcIn");
103 RemoveService(string(Name)+"/RpcOut");
104 }
105 else RemoveService(Name);
106 }
107 else {
108 // Determine type of service
109 if (strstr(Format, "|CMD") != NULL) {
110 *(strstr(Format, "|CMD")) = '\0';
111 AddService(Name, Format, DimCOMMAND);
112 }
113 else if (strstr(Format, "|RPC") != NULL) {
114 *(strstr(Format, "|RPC")) = '\0';
115 if (strchr(Format, ',') != NULL) {
116 *strchr(Format, ',') = '\0';
117 AddService(string(Name)+"/RpcIn", Format, DimCOMMAND);
118 AddService(string(Name)+"/RpcOut", Format+strlen(Format)+1, DimSERVICE);
119 }
120
121 }
122 else {
123 Format[strlen(Format)-1] = '\0';
124 AddService(Name, Format, DimSERVICE);
125 }
126 }
127 }
128 Name = strtok(NULL, "|");
129 }
130 return;
131 }
132
133 // Identify service and repeat to secondary DNS
134 for (int Service=0; Service<List.size(); Service++) if (I == List[Service].DataItem) {
135
136 // Copy service data
137 delete[] List[Service].Data;
138 List[Service].Data = new char [I->getSize()];
139 memcpy(List[Service].Data, I->getData(), I->getSize());
140
141 // Set new service properties and update service
142 List[Service].Service->setQuality(I->getQuality());
143 List[Service].Service->setTimestamp(I->getTimestamp(), I->getTimestampMillisecs());
144 List[Service].Service->updateService(List[Service].Data, I->getSize());
145 }
146}
147
148
149// Command repeating
150void Bridge::commandHandler() {
151
152 sendCommandNB(getCommand()->getName(), getCommand()->getData(), getCommand()->getSize());
153}
154
155
156// Service subscription
157void Bridge::AddService(string Name, char *Format, int Type) {
158
159 // Do not forward DIS_DNS and History services
160 if ((Name.find("DIS_DNS/") != string::npos) || (Name.find("History/") != string::npos)) return;
161
162 // Check if already subscribed to this service
163 for (int i=0; i<List.size(); i++) {
164 if (Name == List[i].Name) return;
165 }
166
167 // Create subscription and service to secondary DNS or new command
168 struct Item New = {Name, NULL, NULL, NULL, NULL};
169
170 if (Type == DimSERVICE) {
171 New.Service = new DimService(Name.c_str(), (char *) Format, New.Data, 0);
172 New.DataItem = new DimStampedInfo(Name.c_str(), NO_LINK, this);
173 }
174 else if (Type == DimCOMMAND) New.Command = new DimCommand(Name.c_str(), Format, this);
175
176 List.push_back(New);
177}
178
179
180// Remove service from watch list (unused pointer are NULL)
181void Bridge::RemoveService(string Name) {
182
183 vector<struct Item>::iterator E;
184 for (E=List.begin(); E<List.end(); ++E) if (Name == (*E).Name) {
185 delete (*E).DataItem;
186 delete (*E).Service;
187 delete[] (*E).Data;
188 delete (*E).Command;
189
190 List.erase(E);
191 }
192}
193
194
195// Main program
196int main(int argc, char *argv[]) {
197
198 // Check command line argument
199 if (argc == 1) {
200 printf("Usage: %s <address of primary DNS> [port] (default port %d)\n", argv[0], DEFAULT_PORT);
201 exit(EXIT_FAILURE);
202 }
203
204 // Static ensures calling of destructor by exit()
205 static Bridge Class(argv[1], argc>2 ? atoi(argv[2]) : DEFAULT_PORT);
206
207 // Sleep until signal caught
208 pause();
209}
Note: See TracBrowser for help on using the repository browser.