Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 1 | /** |
Jon Medhurst | b1d0744 | 2015-05-08 12:04:18 +0100 | [diff] [blame] | 2 | * Copyright (C) ARM Limited 2010-2015. All rights reserved. |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 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 | */ |
| 8 | |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 9 | #include "Sender.h" |
Jon Medhurst | 15ce78d | 2014-04-10 09:02:02 +0100 | [diff] [blame] | 10 | |
| 11 | #include <stdlib.h> |
| 12 | #include <string.h> |
| 13 | #include <unistd.h> |
| 14 | |
| 15 | #include "Buffer.h" |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 16 | #include "Logging.h" |
| 17 | #include "OlySocket.h" |
| 18 | #include "SessionData.h" |
| 19 | |
| 20 | Sender::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 Medhurst | b1d0744 | 2015-05-08 12:04:18 +0100 | [diff] [blame] | 33 | logg->logError("Socket disconnected"); |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 34 | 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 | |
| 50 | Sender::~Sender() { |
Jon Medhurst | 15ce78d | 2014-04-10 09:02:02 +0100 | [diff] [blame] | 51 | // 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 Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 57 | fclose(mDataFile); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | void 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 Medhurst | 96b5615 | 2014-10-30 18:01:15 +0000 | [diff] [blame] | 68 | mDataFile = fopen_cloexec(mDataFileName, "wb"); |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 69 | if (!mDataFile) { |
Jon Medhurst | b1d0744 | 2015-05-08 12:04:18 +0100 | [diff] [blame] | 70 | logg->logError("Failed to open binary file: %s", mDataFileName); |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 71 | handleException(); |
| 72 | } |
| 73 | } |
| 74 | |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 75 | void 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 Medhurst | d369859 | 2013-10-10 16:48:56 +0100 | [diff] [blame] | 93 | unsigned char header[5]; |
| 94 | header[0] = type; |
Jon Medhurst | 15ce78d | 2014-04-10 09:02:02 +0100 | [diff] [blame] | 95 | Buffer::writeLEInt(header + 1, length); |
Jon Medhurst | d369859 | 2013-10-10 16:48:56 +0100 | [diff] [blame] | 96 | mDataSocket->send((char*)&header, sizeof(header)); |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 97 | } |
| 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 Medhurst | 15ce78d | 2014-04-10 09:02:02 +0100 | [diff] [blame] | 103 | mDataSocket->send((const char*)data + pos, min(length - pos, chunkSize)); |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 104 | 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 Medhurst | b1d0744 | 2015-05-08 12:04:18 +0100 | [diff] [blame] | 123 | logg->logError("Failed writing binary file %s", mDataFileName); |
Jon Medhurst | aaf37a3 | 2013-06-11 12:10:56 +0100 | [diff] [blame] | 124 | handleException(); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | pthread_mutex_unlock(&mSendMutex); |
| 129 | } |