Changeset 224
- Timestamp:
- 06/17/10 09:00:51 (15 years ago)
- Location:
- Evidence
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
Evidence/Bridge.cc
r221 r224 7 7 thus serialized by DIM and no Mutex is necessary. 8 8 9 Oliver Grimm, May 2010 9 Remote procedure calls are bridged through their underlying services 10 and commands. 11 12 Oliver Grimm, June 2010 10 13 11 14 \********************************************************************/ … … 21 24 using namespace std; 22 25 26 23 27 // Class declaration 24 28 class Bridge: public DimClient, public EvidenceServer { 25 29 26 30 struct Item { 31 string Name; 32 DimCommand *Command; 27 33 DimStampedInfo *DataItem; 28 34 DimService *Service; … … 34 40 35 41 void infoHandler(); 36 void AddService(string, const char *); 42 void commandHandler(); 43 void AddService(string, char *, int); 37 44 void RemoveService(string); 38 45 … … 42 49 }; 43 50 44 //45 51 // Constructor 46 //47 52 Bridge::Bridge(char *Name, int Port): EvidenceServer(SERVER_NAME) { 48 53 … … 54 59 } 55 60 56 // 61 57 62 // Destructor: Delete all subscriptions and services 58 //59 63 Bridge::~Bridge() { 60 64 61 while (List.size() != 0) RemoveService(List[0]. DataItem->getName());65 while (List.size() != 0) RemoveService(List[0].Name); 62 66 delete ServerList; 63 67 } 64 68 65 // 69 66 70 // Service subscription and repeating 67 //68 71 void Bridge::infoHandler() { 69 72 … … 80 83 RemoveService(string(Token)+"/SERVICE_LIST"); 81 84 } 82 else AddService(string(Token)+"/SERVICE_LIST", "C");85 else AddService(string(Token)+"/SERVICE_LIST", (char *) "C", DimSERVICE); 83 86 84 87 // Skip server IP address and process ID … … 91 94 // If service is SERVICE_LIST, scan and subscribe/unsubscribe to services 92 95 if (strstr(I->getName(), "/SERVICE_LIST") != NULL) { 93 char * Type, *Name = strtok(I->getString(), "+-!|");96 char *Format, *Name = strtok(I->getString(), "+-!|"); 94 97 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); 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 } 99 107 else { 100 Type[strlen(Type)-1] = '\0'; // Isolate service format 101 AddService(Name, Type); 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 } 102 126 } 103 127 } … … 110 134 for (int Service=0; Service<List.size(); Service++) if (I == List[Service].DataItem) { 111 135 112 // Ignores repeating DIS_DNS services113 if (List[Service].Service == NULL) break;114 115 136 // Copy service data 116 137 delete[] List[Service].Data; … … 125 146 } 126 147 127 // 128 // Add service subscription 129 // 130 void Bridge::AddService(string Name, const char *Format) { 148 149 // Command repeating 150 void Bridge::commandHandler() { 151 152 sendCommandNB(getCommand()->getName(), getCommand()->getData(), getCommand()->getSize()); 153 } 154 155 156 // Service subscription 157 void 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; 131 161 132 162 // Check if already subscribed to this service 133 163 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); 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 144 176 List.push_back(New); 145 177 } 146 178 147 179 148 // 149 // Remove service from watch list 150 // 180 // Remove service from watch list (unused pointer are NULL) 151 181 void Bridge::RemoveService(string Name) { 152 182 153 // Find service index154 183 vector<struct Item>::iterator E; 155 for (E=List.begin(); E<List.end(); ++E) if (Name == (*E). DataItem->getName()) {184 for (E=List.begin(); E<List.end(); ++E) if (Name == (*E).Name) { 156 185 delete (*E).DataItem; 157 186 delete (*E).Service; 158 187 delete[] (*E).Data; 188 delete (*E).Command; 189 159 190 List.erase(E); 160 191 } … … 162 193 163 194 164 //165 195 // Main program 166 //167 196 int main(int argc, char *argv[]) { 168 197 198 // Check command line argument 169 199 if (argc == 1) { 170 200 printf("Usage: %s <address of primary DNS> [port] (default port %d)\n", argv[0], DEFAULT_PORT); -
Evidence/Config.cc
r221 r224 74 74 // Open configuration file 75 75 if ((File = fopen(Filename, "r")) == NULL) { 76 Message(FATAL, "Could not open configuration file '%s' (%s) \n", Filename, strerror(errno));76 Message(FATAL, "Could not open configuration file '%s' (%s)", Filename, strerror(errno)); 77 77 } 78 78 … … 81 81 Message(WARN, "Error setting configuration file '%s' to unbuffered mode", Filename); 82 82 } 83 83 84 84 // Create DIM services 85 85 ConfigChanged(); -
Evidence/DColl.cc
r221 r224 95 95 96 96 LogSizeMB = FileSize(LogFile)/1024.0/1024.0; 97 LogSizeService = new DimService(SERVER_NAME "/LogSize kB", LogSizeMB);97 LogSizeService = new DimService(SERVER_NAME "/LogSizeMB", LogSizeMB); 98 98 99 99 DataFilename = new DimService(SERVER_NAME "/CurrentFile", (char *) ""); … … 216 216 // Create direcory if not existing (ignore error if already existing) 217 217 char *Dir; 218 if (asprintf(&Dir, "%s/%d %02d", BaseDir, T->tm_year+1900, T->tm_mon + 1) == -1) {218 if (asprintf(&Dir, "%s/%d", BaseDir, T->tm_year+1900) == -1) { 219 219 Message(FATAL, "asprintf() failed, could not create direcory name"); 220 220 } -
Evidence/Edd/Edd.cc
r222 r224 99 99 100 100 // Update widget 101 void EddLineDisplay::Update(QString Name, int Time, QByteArray Array, QString Format, QString Text) {101 void EddLineDisplay::Update(QString Name, int Time, QByteArray, QString Format, QString Text) { 102 102 103 103 if (ServiceName != Name) return; … … 109 109 setText("n/a"); 110 110 Pal.setColor(QPalette::Base, Qt::lightGray); 111 } 112 else { 113 // Backgound colour determined by last byte 114 switch (Array[Array.size()]) { 111 setPalette(Pal); 112 return; 113 } 114 115 // Message service backgound colour determined by severity 116 if (Name.endsWith("/Message")) { 117 switch (Text.section(' ', 0, 0).toInt()) { 115 118 case 0: Pal.setColor(QPalette::Base, Qt::white); break; 116 119 case 1: Pal.setColor(QPalette::Base, Qt::yellow); break; … … 119 122 default: break; 120 123 } 121 122 if (Format[0].toUpper() != 'C') Text = Text.section(' ', Index, Index); 123 124 if (!ShowAsTime) setText(Text); 125 else setText(QDateTime::fromTime_t(Text.toInt()).toString());126 setCursorPosition(0);127 } 128 124 Text = Text.section(' ', 1); 125 } 126 else if (Format[0].toUpper() != 'C') Text = Text.section(' ', Index, Index); 127 128 if (!ShowAsTime) setText(Text); 129 else setText(QDateTime::fromTime_t(Text.toInt()).toString()); 130 131 setCursorPosition(0); 129 132 setPalette(Pal); 130 133 } -
Evidence/Evidence.cc
r222 r224 5 5 - The server is started with the given name. 6 6 - DIM exit and error handlers are implemented. 7 - The Message service is published (special format, see below).8 It can be updatedwith the Message() method. The text will also be logged.7 - A Message service is published with severity encoding. It can be updated 8 with the Message() method. The text will also be logged. 9 9 - If the severity of a Message() call is FATAL, exit() will be called (with 10 10 this severity, the call to Message() is guranteed not to return). … … 16 16 DIMInfo service into text 17 17 - A terminate-handler is installed for catching unhandled C++ exceptions. 18 19 All memory allocated by the non-static methods will be freed by the18 19 Memory allocated by the non-static methods will be freed by the 20 20 class destructor. 21 21 22 Oliver Grimm, March 200922 Oliver Grimm, June 2010 23 23 24 24 \********************************************************************/ … … 37 37 38 38 // Initialize 39 Status= NULL;40 StdOutText= NULL;39 MessageService = NULL; 40 MessageData = NULL; 41 41 ExitRequest = false; 42 42 ThisServer = this; … … 54 54 // Subscribe to modify service for keeping track of config file changes 55 55 ModifyInfo = new class ConfigUpdate(); 56 56 57 // Message service and initial message 58 MessageService = new DimService((ServerName+"/Message").c_str(), (char *) "I:1;C", NULL, 0); 59 60 string Rev(EVIDENCE_REVISION); 61 Message(INFO, "Server started (%s, compiled %s %s)", (Rev.substr(1, Rev.size()-3)).c_str(),__DATE__, __TIME__); 62 57 63 // Start server 58 string Rev(EVIDENCE_REVISION);59 Rev = Rev.substr(1, Rev.size()-3);60 snprintf(InitMsg, sizeof(InitMsg), "Server started (%s, compiled %s %s)", Rev.c_str(),__DATE__, __TIME__);61 62 Status = new DimService((ServerName+"/Message").c_str(), (char *) "C", InitMsg, strlen(InitMsg)+1);63 StdOut = new DimService((ServerName+"/Textout").c_str(), (char *) "");64 65 64 start(Name); 66 addExitHandler(this); 65 addExitHandler(this); 67 66 } 68 67 … … 72 71 Message(INFO, "Server stopped"); 73 72 74 for (unsigned int i=0; i<ConfigList.size(); i++) { 75 delete[] ConfigList[i].Value; 76 } 73 for (unsigned int i=0; i<ConfigList.size(); i++) delete[] ConfigList[i].Value; 77 74 delete ModifyInfo; 78 79 delete Status; 80 delete StdOut; 75 delete MessageService; 76 delete MessageData; 81 77 } 82 78 … … 90 86 // DIM error handler 91 87 void EvidenceServer::errorHandler(int Severity, int Code, char *Text) { 92 Message(ERROR, "%s (DIM error code %d, severity %d)\n", Text, Code, Severity); 93 } 94 95 // Set status of server 96 // 97 // The message format is special: after the string-terminating '\0' the Severity 98 // is given, terminated by another '\0' The buffer for the DIM service must have 99 // the same lifetime as the DIM service. If Severity is FATAL, exit() will be invoked. 88 Message(ERROR, "%s (DIM error code %d, DIM severity %d)\n", Text, Code, Severity); 89 } 90 91 // Set server message (if Severity is FATAL, exit() will be invoked) 100 92 void EvidenceServer::Message(MessageType Severity, const char *Format, ...) { 101 93 102 94 static const char* StateString[] = {"Info", "Warn", "Error", "Fatal"}; 103 95 static char ErrorString[] = "vasprintf() failed in Message()"; 104 static char SBuf[STATUS_SIZE]; 105 char TBuf[STATUS_SIZE]; 106 char *Tmp; 96 char *Text; 107 97 108 98 // Assemble message from application 109 99 va_list ArgumentPointer; 110 100 va_start(ArgumentPointer, Format); 111 if (vasprintf(&Tmp, Format, ArgumentPointer) == -1) Tmp = ErrorString; 101 if (vasprintf(&Text, Format, ArgumentPointer) == -1) { 102 Text = ErrorString; 103 Severity = ERROR; 104 } 112 105 va_end(ArgumentPointer); 113 106 114 // Create normal string 115 snprintf(TBuf, sizeof(TBuf), "%s (%s): %s", Status->getName(), StateString[Severity], Tmp); 116 117 // Create string with severity encoding 118 snprintf(SBuf, sizeof(SBuf), "%s*", Tmp); 119 SBuf[strlen(SBuf)-1] = '\0'; // new string terminiation replaces '*' 120 SBuf[strlen(SBuf)+1] = Severity; // Severity after new string termination 121 122 if (Tmp != ErrorString) free(Tmp); 107 // Generate new Message structure and free text 108 struct Message *NewMsg = (struct Message *) new char [sizeof(struct Message)+strlen(Text)+1]; 109 NewMsg->Severity = Severity; 110 strcpy(NewMsg->Text, Text); 111 if (Text != ErrorString) free(Text); 123 112 124 113 // Send message to console and log file 125 printf("%s\n", TBuf); 126 DimClient::sendCommandNB("DColl/Log", TBuf); 127 128 // Update DIM status service (including severity encoding) 129 if (Status != NULL) Status->updateService(SBuf, strlen(SBuf)+2); 130 131 // Terminate if message type is fatal 114 printf("%s (%s): %s\n", MessageService->getName(), StateString[Severity], NewMsg->Text); 115 SendToLog("%s (%s): %s", MessageService->getName(), StateString[Severity], NewMsg->Text); 116 117 // Update DIM message service, then delete old message 118 if (MessageService != NULL) { 119 MessageService->updateService(NewMsg, sizeof(struct Message)+strlen(NewMsg->Text)+1); 120 } 121 delete MessageData; 122 MessageData = NewMsg; 123 124 // Terminate if severity if FATAL 132 125 if (Severity == FATAL) exit(EXIT_FAILURE); 133 126 } 134 127 135 // Set text of StdOut service 136 void EvidenceServer::SetStdOut(char *Text) { 137 138 // Copy text to permanent buffer 139 char *Tmp = new char[strlen(Text)+1]; 140 strcpy(Tmp, Text); 141 StdOut->updateService(Tmp); 142 143 // Delete old buffer and save new buffer pointer 144 delete[] StdOutText; 145 StdOutText = Tmp; 146 } 128 129 // Set to central logging server with non-blocking command (may be used in DIM handler) 130 void EvidenceServer::SendToLog(const char *Format, ...) { 131 132 char *Buffer; 133 int Ret; 134 135 // Evaluate variable argument list 136 va_list ArgumentPointer; 137 va_start(ArgumentPointer, Format); 138 Ret = vasprintf(&Buffer, Format, ArgumentPointer); 139 va_end(ArgumentPointer); 140 141 // Send to logger 142 if (Ret != -1) { 143 DimClient::sendCommandNB("DColl/Log", Buffer); 144 free (Buffer); 145 } 146 else Message(ERROR, "Could not create logging text in SendToLog(), vasprintf() failed"); 147 } 148 147 149 148 150 // Get configuration data … … 191 193 192 194 // Create new entry in item list, allocate memory and copy data to this memory 195 ConfigList[ItemNo].Name = Item; 193 196 ConfigList[ItemNo].Value = new char [strlen(Result)+1]; 194 ConfigList[ItemNo].Name = Item;195 197 strcpy(ConfigList[ItemNo].Value, Result); 196 198 ConfigList[ItemNo].Time = ModifyInfo->LastModifyTime; … … 208 210 static bool Called = false; 209 211 212 // At first invocation just request exit 210 213 if (!Called) { 211 214 Called = true; … … 226 229 227 230 if (Terminating) { 228 snprintf(Msg, sizeof(Msg), "%s: Terminate() called recursively, calling abort()", ThisServer-> Status->getName());231 snprintf(Msg, sizeof(Msg), "%s: Terminate() called recursively, calling abort()", ThisServer->MessageService->getName()); 229 232 printf("%s\n", Msg); 230 233 DimClient::sendCommandNB("DColl/Log", Msg); … … 259 262 260 263 // Translates DIMInfo to string (memory has to be freed by caller) 261 // Static method : it cannot report memory allocation errors via Message()264 // Static method, cannot report memory allocation errors via Message() but returns NULL 262 265 char *EvidenceServer::ToString(DimInfo *Item) { 263 266 … … 266 269 // Safety check 267 270 if (Item->getSize() < 1) return NULL; 271 272 // Message structure format handled 273 if (strcmp(Item->getFormat(), "I:1;C") == 0) { 274 struct Message *Msg = (struct Message *) Item->getData(); 275 if (asprintf(&Text, "%d %s", Msg->Severity, Msg->Text) == -1) return NULL; 276 else return Text; 277 } 268 278 269 279 // Structure: print hex representation (3 characters per byte) -
Evidence/Evidence.h
r222 r224 19 19 // Class declation of Evidence server 20 20 class EvidenceServer: public DimServer { 21 21 22 private: 22 23 // This class will contain in LastModifyTime always 23 24 // the unix time of the last config file update 24 class ConfigUpdate: public DimClient {25 DimInfo *ModifyInfo;25 class ConfigUpdate: public DimClient, public DimRpcInfo { 26 DimInfo *ModifyInfo; 26 27 27 28 public: 28 ConfigUpdate() {29 ConfigUpdate(): DimRpcInfo("ConfigRequest", NO_LINK) { 29 30 LastModifyTime = 0; 30 31 ModifyInfo = new DimInfo("Config/ModifyTime", NO_LINK, this); … … 33 34 delete ModifyInfo; 34 35 } 36 void Request(const char *What){ 37 setData((char *) What); 38 } 39 35 40 void infoHandler(){ 36 41 if (EvidenceServer::ServiceOK(getInfo())) LastModifyTime = getInfo()->getInt(); 37 42 } 43 44 void rpcInfoHandler(){ 45 //printf("Received %s\n", getString()); 46 } 47 38 48 int LastModifyTime; 39 49 }; 50 51 private: 40 52 41 53 struct ConfigItem { … … 46 58 std::vector<struct ConfigItem> ConfigList; 47 59 60 struct Message { 61 int Severity; 62 char Text[]; 63 }; 64 48 65 std::string ServerName; 49 DimService *Status, *StdOut; 66 DimService *MessageService; 67 struct Message *MessageData; 50 68 class ConfigUpdate *ModifyInfo; 51 52 char InitMsg[STATUS_SIZE];53 int LastModifyTime;54 char *StdOutText;55 69 56 70 static void SignalHandler(int); // static for signal() … … 66 80 67 81 void Message(MessageType, const char *, ...); 68 void Se tStdOut(char *);82 void SendToLog(const char *, ...); 69 83 char* GetConfig(std::string, const char * = NULL); 70 84 static char* ToString(DimInfo *); -
Evidence/History.cc
r222 r224 259 259 // Set minimum required change if given in configuratrion 260 260 char *Pnt = strstr(Change, Name.c_str()); 261 261 262 if (Pnt != NULL && *(Pnt+Name.size()) == ':') New.MinAbsChange = atof(Pnt+Name.size()+1); 262 263 else New.MinAbsChange = 0; -
Evidence/readme.txt
r222 r224 29 29 FATAL. The erroneous expression is ignored in the following. 30 30 25/5/2010 Service history remains available if service itself become unavailable. If not 31 yet in memory, reading from historyfile is tried. Improved error handling of31 yet in memory, reading from file is tried. Improved error handling of 32 32 history files. 33 33 28/5/2010 Changed name of 'State' service to 'Message' to better reflect its functionality. … … 35 35 30/5/2010 Created Bridge server that repeats services from one DNS to another. 36 36 Service quality now also written to slow data file. 37 31/5/2010 Configuration file format nowfollows semi-standard INI format.37 31/5/2010 Configuration file format follows semi-standard INI format. 38 38 7/6/2010 Separated History service from DColl. History format changed, now includes 39 39 service format (allows history access also when service is unavailable). 40 11/6/2010 Bridge does not forward history service 41 17/6/2010 Added SendToLog() method. Changed severity encoding of Message service to 42 use standard DIM structure of format "I:1;C" 40 43 41 44
Note:
See TracChangeset
for help on using the changeset viewer.