]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blob - daemon/StreamlineSetup.cpp
8473f8fb3d6a100750d73bca8aa850d14d74c169
[android-sdk/arm-ds5-gator.git] / daemon / StreamlineSetup.cpp
1 /**
2  * Copyright (C) ARM Limited 2011. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
9 typedef long long int64_t;
10 typedef unsigned long long uint64_t;
11 #include <string.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <dirent.h>
15 #include <sys/types.h>
16 #include <arpa/inet.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include "XMLOut.h"
20 #include "Sender.h"
21 #include "Logging.h"
22 #include "XMLReader.h"
23 #include "RequestXML.h"
24 #include "OlyUtility.h"
25 #include "SessionData.h"
26 #include "CapturedXML.h"
27 #include "StreamlineSetup.h"
28 #include "ConfigurationXML.h"
30 extern void handleException();
32 static const char*      TAG_SESSION = "session";
33 static const char*      TAG_CONFIGURATIONS = "configurations";
35 StreamlineSetup::StreamlineSetup(OlySocket* s) {
36         bool ready = false;
37         char *data = NULL;
38         int type;
40         socket = s;
41         mSessionXML = NULL;
43         // Receive commands from Streamline (master)
44         while (!ready) {
45                 // receive command over socket
46                 gSessionData.mWaitingOnCommand = true;
47                 data = readCommand(&type);
49                 // parse and handle data
50                 switch (type) {
51                         case COMMAND_REQUEST_XML:
52                                 handleRequest(data);
53                                 break;
54                         case COMMAND_DELIVER_XML:
55                                 handleDeliver(data);
56                                 break;
57                         case COMMAND_APC_START:
58                                 logg->logMessage("Received apc start request");
59                                 ready = true;
60                                 break;
61                         case COMMAND_APC_STOP:
62                                 // Clear error log so no text appears on console and exit
63                                 logg->logMessage("Received apc stop request before apc start request");
64                                 logg->logError(__FILE__, __LINE__, "");
65                                 handleException();
66                                 break;
67                         case COMMAND_DISCONNECT:
68                                 // Clear error log so no text appears on console and exit
69                                 logg->logMessage("Received disconnect command");
70                                 logg->logError(__FILE__, __LINE__, "");
71                                 handleException();
72                                 break;
73                         case COMMAND_PING:
74                                 logg->logMessage("Received ping command");
75                                 sendData(NULL, 0, RESPONSE_ACK);
76                                 break;
77                         default:
78                                 logg->logError(__FILE__, __LINE__, "Target error: Unknown command type, %d", type);
79                                 handleException();
80                 }
82                 delete(data);
83         }
84 }
86 StreamlineSetup::~StreamlineSetup() {
87         if (mSessionXML)
88                 free(mSessionXML);
89 }
91 char* StreamlineSetup::readCommand(int* command) {
92         char type;
93         char* data;
94         int response, length;
96         // receive type
97         response = socket->receiveNBytes(&type, sizeof(type));
99         // After receiving a single byte, we are no longer waiting on a command
100         gSessionData.mWaitingOnCommand = false;
102         if (response < 0) {
103                 logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
104                 handleException();
105         }
107         // receive length
108         response = socket->receiveNBytes((char*)&length, sizeof(length));
109         if (response < 0) {
110                 logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
111                 handleException();
112         }
114         // add artificial limit
115         if ((length < 0) || length > 1024 * 1024) {
116                 logg->logError(__FILE__, __LINE__, "Target error: Invalid length received, %d", length);
117                 handleException();
118         }
120         // allocate memory to contain the xml file, size of zero returns a zero size object
121         data = (char*)calloc(length + 1, 1);
122         if (data == NULL) {
123                 logg->logError(__FILE__, __LINE__, "Unable to allocate memory for xml");
124                 handleException();
125         }
127         // receive data
128         response = socket->receiveNBytes(data, length);
129         if (response < 0) {
130                 logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
131                 handleException();
132         }
134         // null terminate the data for string parsing
135         if (length > 0) {
136                 data[length] = 0;
137         }
139         *command = type;
140         return data;
143 void StreamlineSetup::handleRequest(char* xml) {
144         RequestXML request(xml);
146         if (request.parameters.protocol) {
147                 sendProtocol();
148                 logg->logMessage("Sent protocol xml response");
149         } else if (request.parameters.events) {
150                 sendEvents();
151                 logg->logMessage("Sent events xml response");
152         } else if (request.parameters.configuration) {
153                 sendConfiguration();
154                 logg->logMessage("Sent configuration xml response");
155         } else if (request.parameters.counters) {
156                 sendCounters();
157                 logg->logMessage("Sent counters xml response");
158         } else if (request.parameters.session) {
159                 sendData(mSessionXML, strlen(mSessionXML), RESPONSE_XML);
160                 logg->logMessage("Sent session xml response");
161         } else if (request.parameters.captured) {
162                 CapturedXML capturedXML;
163                 const char* capturedText = capturedXML.getXML();
164                 sendData(capturedText, strlen(capturedText), RESPONSE_XML);
165                 logg->logMessage("Sent captured xml response");
166         } else if (request.parameters.defaults) {
167                 sendDefaults();
168                 logg->logMessage("Sent default configuration xml response");
169         } else {
170                 char error[] = "Unknown request";
171                 sendData(error, strlen(error), RESPONSE_NAK);
172                 logg->logMessage("Received unknown request:\n%s", xml);
173         }
176 typedef enum {UNKNOWN, SESSION_XML, CONFIGURATION_XML} delivery_type_t;
177 void StreamlineSetup::handleDeliver(char* xml) {
178         delivery_type_t type = UNKNOWN; 
180         // Determine xml type
181         XMLReader reader(xml);
182         char * tag = reader.nextTag();
183         while(tag != 0) {
184                 if (strcmp(tag, TAG_SESSION) == 0) {
185                         type = SESSION_XML;
186                         break;
187                 } else if (strcmp(tag, TAG_CONFIGURATIONS) == 0) {
188                         type = CONFIGURATION_XML;
189                         break;
190                 }
191                 tag = reader.nextTag();
192         }
194         switch (type) {
195                 case UNKNOWN:
196                         logg->logMessage("Received unknown delivery type: %d", type);
197                         sendData(NULL, 0, RESPONSE_NAK);
198                         break;
199                 case SESSION_XML:
200                         // Parse the session xml
201                         gSessionData.parseSessionXML(xml);
203                         // Save xml
204                         mSessionXML = strdup(xml);
205                         if (mSessionXML == NULL) {
206                                 logg->logError(__FILE__, __LINE__, "malloc failed for size %d", strlen(xml) + 1);
207                                 handleException();
208                         }
209                         sendData(NULL, 0, RESPONSE_ACK);
210                         logg->logMessage("Received session xml");
211                         break;
212                 case CONFIGURATION_XML:
213                         writeConfiguration(xml);
214                         sendData(NULL, 0, RESPONSE_ACK);
215                         logg->logMessage("Received configuration xml");
216                         break;
217         }
220 void StreamlineSetup::sendData(const char* data, int length, int type) {
221         socket->send((char*)&type, 1);
222         socket->send((char*)&length, sizeof(length));
223         socket->send((char*)data, length);
226 void StreamlineSetup::sendProtocol() {
227         XMLOut out;
228         out.xmlHeader();
230         out.startElement("protocol");
231         out.attributeInt("version", PROTOCOL_VERSION);
232         out.endElement("protocol");
234         sendString(out.getXmlString(), RESPONSE_XML);
237 void StreamlineSetup::sendEvents() {
238 #include "events_xml.h"
239         char path[PATH_MAX];
240         char * buffer;
241         unsigned int size = 0;
243         util->getApplicationFullPath(path, sizeof(path));
244         strncat(path, "events.xml", sizeof(path) - strlen(path) - 1);
245         buffer = util->readFromDisk(path, &size);
246         if (buffer == NULL) {
247                 logg->logMessage("Unable to locate events.xml, using default");
248                 buffer = (char*)events_xml;
249                 size = events_xml_len;
250         }
252         sendData(buffer, size, RESPONSE_XML);
253         if (buffer != (char*)events_xml) {
254                 free(buffer);
255         }
258 void StreamlineSetup::sendConfiguration() {
259         ConfigurationXML xml;
261         const char* string = xml.getConfigurationXML();
262         sendData(string, strlen(string), RESPONSE_XML);
265 void StreamlineSetup::sendDefaults() {
266 #include "configuration_xml.h"
267         // Send the config built into the binary
268         char* xml = (char*)configuration_xml;
269         unsigned int size = configuration_xml_len;
271         // Artificial size restriction
272         if (size > 1024*1024) {
273                 logg->logError(__FILE__, __LINE__, "Corrupt default configuration file");
274                 handleException();
275         }
277         sendData(xml, size, RESPONSE_XML);
280 #include <dirent.h>
281 void StreamlineSetup::sendCounters() {
282         XMLOut out;
283         struct dirent *ent;
285         // counters.xml is simply a file listing of /dev/gator/events
286         DIR* dir = opendir("/dev/gator/events");
287         if (dir == NULL) {
288                 logg->logError(__FILE__, __LINE__, "Cannot create counters.xml since unable to read /dev/gator/events");
289                 handleException();
290         }
292         out.xmlHeader();
293         out.startElement("counters");
294         while ((ent = readdir(dir)) != NULL) {
295                 // skip hidden files, current dir, and parent dir
296                 if (ent->d_name[0] == '.')
297                         continue;
298                 out.startElement("counter");
299                 out.attributeString("name", ent->d_name);
300                 out.endElement("counter");
301         }
302         out.endElement("counters");
303         closedir (dir);
305         sendString(out.getXmlString(), RESPONSE_XML);
308 void StreamlineSetup::writeConfiguration(char* xml) {
309         char path[PATH_MAX];
311         util->getApplicationFullPath(path, sizeof(path));
312         strncat(path, "configuration.xml", sizeof(path) - strlen(path) - 1);
313         if (util->writeToDisk(path, xml) < 0) {
314                 logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", path);
315                 handleException();
316         }
318         new ConfigurationXML();