blob: d7ad757165a2923a3970f0e989f59096b797115f [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/**
Jon Medhurstb1d07442015-05-08 12:04:18 +01002 * Copyright (C) ARM Limited 2010-2015. All rights reserved.
Jon Medhurstaaf37a32013-06-11 12:10:56 +01003 *
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 */
8
Jon Medhurstaaf37a32013-06-11 12:10:56 +01009#include "Sender.h"
Jon Medhurst15ce78d2014-04-10 09:02:02 +010010
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14
15#include "Buffer.h"
Jon Medhurstaaf37a32013-06-11 12:10:56 +010016#include "Logging.h"
17#include "OlySocket.h"
18#include "SessionData.h"
19
20Sender::Sender(OlySocket* socket) {
21 mDataFile = NULL;
22 mDataSocket = NULL;
23
24 // Set up the socket connection
25 if (socket) {
26 char streamline[64] = {0};
27 mDataSocket = socket;
28
29 // Receive magic sequence - can wait forever
30 // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+
31 while (strcmp("STREAMLINE", streamline) != 0) {
32 if (mDataSocket->receiveString(streamline, sizeof(streamline)) == -1) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010033 logg->logError("Socket disconnected");
Jon Medhurstaaf37a32013-06-11 12:10:56 +010034 handleException();
35 }
36 }
37
38 // Send magic sequence - must be done first, after which error messages can be sent
39 char magic[32];
40 snprintf(magic, 32, "GATOR %i\n", PROTOCOL_VERSION);
41 mDataSocket->send(magic, strlen(magic));
42
43 gSessionData->mWaitingOnCommand = true;
44 logg->logMessage("Completed magic sequence");
45 }
46
47 pthread_mutex_init(&mSendMutex, NULL);
48}
49
50Sender::~Sender() {
Jon Medhurst15ce78d2014-04-10 09:02:02 +010051 // Just close it as the client socket is on the stack
52 if (mDataSocket != NULL) {
53 mDataSocket->closeSocket();
54 mDataSocket = NULL;
55 }
56 if (mDataFile != NULL) {
Jon Medhurstaaf37a32013-06-11 12:10:56 +010057 fclose(mDataFile);
58 }
59}
60
61void Sender::createDataFile(char* apcDir) {
62 if (apcDir == NULL) {
63 return;
64 }
65
66 mDataFileName = (char*)malloc(strlen(apcDir) + 12);
67 sprintf(mDataFileName, "%s/0000000000", apcDir);
Jon Medhurst96b56152014-10-30 18:01:15 +000068 mDataFile = fopen_cloexec(mDataFileName, "wb");
Jon Medhurstaaf37a32013-06-11 12:10:56 +010069 if (!mDataFile) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010070 logg->logError("Failed to open binary file: %s", mDataFileName);
Jon Medhurstaaf37a32013-06-11 12:10:56 +010071 handleException();
72 }
73}
74
Jon Medhurstaaf37a32013-06-11 12:10:56 +010075void Sender::writeData(const char* data, int length, int type) {
76 if (length < 0 || (data == NULL && length > 0)) {
77 return;
78 }
79
80 // Multiple threads call writeData()
81 pthread_mutex_lock(&mSendMutex);
82
83 // Send data over the socket connection
84 if (mDataSocket) {
85 // Start alarm
86 const int alarmDuration = 8;
87 alarm(alarmDuration);
88
89 // Send data over the socket, sending the type and size first
90 logg->logMessage("Sending data with length %d", length);
91 if (type != RESPONSE_APC_DATA) {
92 // type and length already added by the Collector for apc data
Jon Medhurstd3698592013-10-10 16:48:56 +010093 unsigned char header[5];
94 header[0] = type;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010095 Buffer::writeLEInt(header + 1, length);
Jon Medhurstd3698592013-10-10 16:48:56 +010096 mDataSocket->send((char*)&header, sizeof(header));
Jon Medhurstaaf37a32013-06-11 12:10:56 +010097 }
98
99 // 100Kbits/sec * alarmDuration sec / 8 bits/byte
100 const int chunkSize = 100*1000 * alarmDuration / 8;
101 int pos = 0;
102 while (true) {
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100103 mDataSocket->send((const char*)data + pos, min(length - pos, chunkSize));
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100104 pos += chunkSize;
105 if (pos >= length) {
106 break;
107 }
108
109 // Reset the alarm
110 alarm(alarmDuration);
111 logg->logMessage("Resetting the alarm");
112 }
113
114 // Stop alarm
115 alarm(0);
116 }
117
118 // Write data to disk as long as it is not meta data
119 if (mDataFile && type == RESPONSE_APC_DATA) {
120 logg->logMessage("Writing data with length %d", length);
121 // Send data to the data file
122 if (fwrite(data, 1, length, mDataFile) != (unsigned int)length) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100123 logg->logError("Failed writing binary file %s", mDataFileName);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100124 handleException();
125 }
126 }
127
128 pthread_mutex_unlock(&mSendMutex);
129}