1 /**
2 * Copyright (C) ARM Limited 2010-2012. 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 #include <string.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <sys/types.h>
13 #include <arpa/inet.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include "Sender.h"
17 #include "Logging.h"
18 #include "SessionData.h"
20 extern void handleException();
22 Sender::Sender(OlySocket* socket) {
23 mDataFile = NULL;
24 mDataSocket = NULL;
26 // Set up the socket connection
27 if (socket) {
28 char streamline[64] = {0};
29 mDataSocket = socket;
31 // Receive magic sequence - can wait forever
32 // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+
33 while (strcmp("STREAMLINE", streamline) != 0) {
34 if (mDataSocket->receiveString(streamline, sizeof(streamline)) == -1) {
35 logg->logError(__FILE__, __LINE__, "Socket disconnected");
36 handleException();
37 }
38 }
40 // Send magic sequence - must be done first, afterwhich error messages can be sent
41 char magic[] = {'G', 'A', 'T', 'O', 'R', '\n'};
42 mDataSocket->send(magic, sizeof(magic));
44 gSessionData->mWaitingOnCommand = true;
45 logg->logMessage("Completed magic sequence");
46 }
48 pthread_mutex_init(&mSendMutex, NULL);
49 }
51 Sender::~Sender() {
52 delete mDataSocket;
53 mDataSocket = NULL;
54 if (mDataFile) {
55 fclose(mDataFile);
56 }
57 }
59 void Sender::createDataFile(char* apcDir) {
60 if (apcDir == NULL) {
61 return;
62 }
64 mDataFileName = (char*)malloc(strlen(apcDir) + 12);
65 sprintf(mDataFileName, "%s/0000000000", apcDir);
66 mDataFile = fopen(mDataFileName, "wb");
67 if (!mDataFile) {
68 logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", mDataFileName);
69 handleException();
70 }
71 }
73 void Sender::writeData(const char* data, int length, int type) {
74 if (length < 0 || (data == NULL && length > 0)) {
75 return;
76 }
78 // Multiple threads call writeData()
79 pthread_mutex_lock(&mSendMutex);
81 // Send data over the socket connection
82 if (mDataSocket) {
83 // Start alarm
84 alarm(8);
86 // Send data over the socket, sending the type and size first
87 logg->logMessage("Sending data with length %d", length);
88 if (type != RESPONSE_APC_DATA) {
89 // type and length already added by the Collector for apc data
90 mDataSocket->send((char*)&type, 1);
91 mDataSocket->send((char*)&length, sizeof(length));
92 }
93 mDataSocket->send((char*)data, length);
95 // Stop alarm
96 alarm(0);
97 }
99 // Write data to disk as long as it is not meta data
100 if (mDataFile && type == RESPONSE_APC_DATA) {
101 logg->logMessage("Writing data with length %d", length);
102 // Send data to the data file
103 if (fwrite(data, 1, length, mDataFile) != (unsigned int)length) {
104 logg->logError(__FILE__, __LINE__, "Failed writing binary file %s", mDataFileName);
105 handleException();
106 }
107 }
109 pthread_mutex_unlock(&mSendMutex);
110 }