source: Evidence/Bridge.cc@ 223

Last change on this file since 223 was 221, checked in by ogrimm, 16 years ago
Added Bridge server, History service separated from DColl
File size: 4.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 Oliver Grimm, May 2010
10
11\********************************************************************/
12
13#define SERVER_NAME "Bridge"
14#include "Evidence.h"
15
16#include <string>
17#include <vector>
18
19const int DEFAULT_PORT = 2505;
20
21using namespace std;
22
23// Class declaration
24class Bridge: public DimClient, public EvidenceServer {
25
26 struct Item {
27 DimStampedInfo *DataItem;
28 DimService *Service;
29 char *Data;
30 };
31 vector<struct Item> List;
32
33 DimInfo *ServerList;
34
35 void infoHandler();
36 void AddService(string, const char *);
37 void RemoveService(string);
38
39 public:
40 Bridge(char *, int);
41 ~Bridge();
42};
43
44//
45// Constructor
46//
47Bridge::Bridge(char *Name, int Port): EvidenceServer(SERVER_NAME) {
48
49 // Set primary DIM network to subscribe from
50 DimClient::setDnsNode(Name, Port);
51
52 // Subsribe to top-level server list
53 ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
54}
55
56//
57// Destructor: Delete all subscriptions and services
58//
59Bridge::~Bridge() {
60
61 while (List.size() != 0) RemoveService(List[0].DataItem->getName());
62 delete ServerList;
63}
64
65//
66// Service subscription and repeating
67//
68void Bridge::infoHandler() {
69
70 DimInfo *I = getInfo();
71
72 // Check if service available
73 if (!ServiceOK(I)) return;
74
75 // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services
76 if (strcmp(I->getName(), "DIS_DNS/SERVER_LIST") == 0) {
77 char *Token = strtok(I->getString(), "+-!@");
78 while (Token != NULL) {
79 if (*I->getString() == '-' || *I->getString() == '!') {
80 RemoveService(string(Token)+"/SERVICE_LIST");
81 }
82 else AddService(string(Token)+"/SERVICE_LIST", "C");
83
84 // Skip server IP address and process ID
85 Token = strtok(NULL, "|");
86 Token = strtok(NULL, "@");
87 }
88 return;
89 }
90
91 // If service is SERVICE_LIST, scan and subscribe/unsubscribe to services
92 if (strstr(I->getName(), "/SERVICE_LIST") != NULL) {
93 char *Type, *Name = strtok(I->getString(), "+-!|");
94 while (Name != NULL) {
95 // Only consider DIM services (not commands and RPCs)
96 if (((Type = strtok(NULL, "\n")) != NULL) &&
97 (strstr(Type, "|CMD") == NULL) && (strstr(Type, "|RPC") == NULL)) {
98 if (*I->getString() == '-' || *I->getString() == '!') RemoveService(Name);
99 else {
100 Type[strlen(Type)-1] = '\0'; // Isolate service format
101 AddService(Name, Type);
102 }
103 }
104 Name = strtok(NULL, "|");
105 }
106 return;
107 }
108
109 // Identify service and repeat to secondary DNS
110 for (int Service=0; Service<List.size(); Service++) if (I == List[Service].DataItem) {
111
112 // Ignores repeating DIS_DNS services
113 if (List[Service].Service == NULL) break;
114
115 // Copy service data
116 delete[] List[Service].Data;
117 List[Service].Data = new char [I->getSize()];
118 memcpy(List[Service].Data, I->getData(), I->getSize());
119
120 // Set new service properties and update service
121 List[Service].Service->setQuality(I->getQuality());
122 List[Service].Service->setTimestamp(I->getTimestamp(), I->getTimestampMillisecs());
123 List[Service].Service->updateService(List[Service].Data, I->getSize());
124 }
125}
126
127//
128// Add service subscription
129//
130void Bridge::AddService(string Name, const char *Format) {
131
132 // Check if already subscribed to this service
133 for (int i=0; i<List.size(); i++) {
134 if (Name == List[i].DataItem->getName()) return;
135 }
136
137 // Create subscription and new service to secondary DNS (do not forward DIS_DNS services)
138 struct Item New;
139
140 New.Data = NULL;
141 if (Name.find("DIS_DNS/") != string::npos) New.Service = NULL;
142 else New.Service = new DimService(Name.c_str(), (char *) Format, New.Data, 0);
143 New.DataItem = new DimStampedInfo(Name.c_str(), NO_LINK, this);
144 List.push_back(New);
145}
146
147
148//
149// Remove service from watch list
150//
151void Bridge::RemoveService(string Name) {
152
153 // Find service index
154 vector<struct Item>::iterator E;
155 for (E=List.begin(); E<List.end(); ++E) if (Name == (*E).DataItem->getName()) {
156 delete (*E).DataItem;
157 delete (*E).Service;
158 delete[] (*E).Data;
159 List.erase(E);
160 }
161}
162
163
164//
165// Main program
166//
167int main(int argc, char *argv[]) {
168
169 if (argc == 1) {
170 printf("Usage: %s <address of primary DNS> [port] (default port %d)\n", argv[0], DEFAULT_PORT);
171 exit(EXIT_FAILURE);
172 }
173
174 // Static ensures calling of destructor by exit()
175 static Bridge Class(argv[1], argc>2 ? atoi(argv[2]) : DEFAULT_PORT);
176
177 // Sleep until signal caught
178 pause();
179}
Note: See TracBrowser for help on using the repository browser.