HPCToolkit
DataSocketStream.cpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL: https://hpctoolkit.googlecode.com/svn/branches/hpctoolkit-hpcserver/src/tool/hpcserver/DataSocketStream.cpp $
6 // $Id: DataSocketStream.cpp 4306 2013-07-17 21:19:13Z laksono@gmail.com $
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // $HeadURL: https://hpctoolkit.googlecode.com/svn/branches/hpctoolkit-hpcserver/src/tool/hpcserver/DataSocketStream.cpp $
51 //
52 // Purpose:
53 // An approximate implementation of Java's DataOutputStream, DataInputStream,
54 // combined with the actual socket code to make it all work. Provides useful,
55 // yet fairly direct access to the socket.
56 //
57 // Description:
58 // [The set of functions, macros, etc. defined in the file]
59 //
60 //***************************************************************************
61 
62 #include <stdio.h>//fread, fwrite, etc.
63 #include <cstring> //For memset
64 #include <iostream>
65 #include <string>//for string
66 #include <cstring>//for strerror
67 
68 #include <sys/socket.h>
69 #include <unistd.h> // close socket
70 #include <arpa/inet.h> //htons
71 #include <sys/types.h>
72 #include <netinet/in.h>
73 #include <errno.h>
74 
75 #include "DataSocketStream.hpp"
76 #include "ByteUtilities.hpp"
77 #include "Constants.hpp"
78 
79 namespace TraceviewerServer
80 {
81  using namespace std;
82 
84  {
85  //Do nothing because this is used when the CompressingDataSocket is constructed, which means we already have a socket constructed that we want to use
86  }
87 
88  DataSocketStream::DataSocketStream(int _Port, bool Accept = true)
89  {
90  port = _Port;
91 
92  unopenedSocketFD = socket(PF_INET, SOCK_STREAM, 0);
93  if (unopenedSocketFD == -1)
94  cerr << "Could not create socket" << endl;
95  //bind
96  sockaddr_in Address;
97  memset(&Address, 0, sizeof(Address));
98  Address.sin_family = AF_INET;
99  Address.sin_port = htons(_Port);
100  Address.sin_addr.s_addr = INADDR_ANY;
101  int err = bind(unopenedSocketFD, (sockaddr*) &Address, sizeof(Address));
102  if (err)
103  {
104  if (errno == EADDRINUSE)
105  cerr<< "Could not bind socket because socket is already in use. "<<
106  "Make sure you have closed hpctraceviewer, wait 30 seconds and try again. " <<
107  "Alternatively, you can choose a port other than "<< _Port<<"."<<endl;
108  else
109  cerr << "Could not bind socket. Error was " << strerror(errno) << endl;
110  throw ERROR_SOCKET_IN_USE;
111  }
112  //listen
113  err = listen(unopenedSocketFD, 5);
114  if (err)
115  cerr<<"Listen failed: " << strerror(errno)<<endl;
116  if (Accept)
117  {
118  cout << "Waiting for connection on port " << getPort() << endl;
119  acceptSocket();
120  }
121  }
123  {
124  //accept
125  sockaddr_in client;
126  unsigned int len = sizeof(client);
127  socketDesc = accept(unopenedSocketFD, (sockaddr*) &client, &len);
128  if (socketDesc < 0)
129  cerr << "Error on accept" << endl;
130  file = fdopen(socketDesc, "r+b"); //read, write, binary
131  }
132 
134  {
135  if (port == 0)
136  {
137  //http://stackoverflow.com/questions/4046616/sockets-how-to-find-out-what-port-and-address-im-assigned
138  struct sockaddr_in sin;
139  socklen_t len = sizeof(sin);
140  if (getsockname(unopenedSocketFD, (struct sockaddr *) &sin, &len) == -1)
141  {
142  cerr << "Could not obtain port" << endl;
143  return 0;
144  }
145  else
146  return ntohs(sin.sin_port);
147  }
148  else
149  {
150  return port;
151  }
152  }
153 
155  {
156  fclose(file);
157  shutdown(socketDesc, SHUT_RDWR);
158  close(socketDesc);
159  close(unopenedSocketFD);
160  }
161 
162  void DataSocketStream::writeInt(int toWrite)
163  {
164  char Buffer[4];
165  ByteUtilities::writeInt(Buffer, toWrite);
166  fwrite(Buffer, 4, 1, file);
167  }
169  {
170  char Buffer[8];
171  ByteUtilities::writeLong(Buffer, toWrite);
172  fwrite(Buffer, 8, 1, file);
173  }
174 
175  void DataSocketStream::writeRawData(char* Data, int Length)
176  {
177  int r = fwrite(Data, 1, Length, file);
178  if (r != Length)
179  cerr<<"Only wrote "<<r << " / " <<Length<<endl;
180  }
181 
182  void DataSocketStream::writeString(string toWrite)
183  {
184  writeShort(toWrite.length());
185  fwrite(toWrite.c_str(), toWrite.length(), 1, file);
186  }
187 
188  void DataSocketStream::writeShort(short toWrite)
189  {
190  char Buffer[2];
191  ByteUtilities::writeShort(Buffer, toWrite);
192  fwrite(Buffer, 2, 1, file);
193  }
194 
196  {
197  int e = fflush(file);
198  if (e == EOF)
199  cerr << "Error on sending" << endl;
200  }
201 
203  {
204  char Af[SIZEOF_INT];
205  int err = fread(Af, 1, SIZEOF_INT, file);
206  if (err != SIZEOF_INT)
207  throw ERROR_READ_TOO_LITTLE;
208  return ByteUtilities::readInt(Af);
209 
210  }
211 
213  {
214  char Af[SIZEOF_LONG];
215  int err = fread(Af, 1, SIZEOF_LONG, file);
216  if (err != SIZEOF_LONG)
217  throw ERROR_READ_TOO_LITTLE;
218  return ByteUtilities::readLong(Af);
219 
220  }
221 
223  {
224  char Af[SIZEOF_SHORT];
225  int err = fread(Af, 1, SIZEOF_SHORT, file);
226  if (err != 2)
227  throw ERROR_READ_TOO_LITTLE;
228  return ByteUtilities::readShort(Af);
229  }
231  {
232  char Af[SIZEOF_BYTE];
233  int err = fread(Af, 1, SIZEOF_BYTE, file);
234  if (err != 1)
235  throw ERROR_READ_TOO_LITTLE;
236  return Af[0];
237  }
238 
240  {
241 
242  short Len = readShort();
243 
244  char* Msg = new char[Len + 1];
245  int err = fread(Msg, 1, Len, file);
246  if (err != Len)
247  throw ERROR_READ_TOO_LITTLE;
248 
249  Msg[Len] = '\0';
250 
251  string SF(Msg);
252  //The string constructor copies the array, and we don't want to leak the memory
253  delete[] Msg;
254  return SF;
255  }
256 
258  {
259  Long longForm = readLong();
260  return ByteUtilities::convertLongToDouble(longForm);
261  }
263  {
265  writeLong(longForm);
266  }
267 
269  {
270  if (e == 0)
271  {
272  cout << "Connection closed" << endl; // EOF
273  throw ERROR_STREAM_CLOSED;
274  }
275  else if (e == -1)
276  throw e; // Some other error.
277  }
278 
280  {
281  return socketDesc;
282  }
283 } /* namespace TraceviewerServer */
#define SIZEOF_LONG
Definition: Constants.hpp:66
err
Definition: names.cpp:1
static void writeInt(char *buffer, int ToWrite)
#define SIZEOF_SHORT
Definition: Constants.hpp:68
#define SIZEOF_INT
Definition: Constants.hpp:67
size_t MONITOR_EXT_WRAP_NAME() fread(void *ptr, size_t size, size_t count, FILE *stream)
Definition: io-over.c:226
virtual void writeRawData(char *, int)
static int64_t readLong(char *buffer)
static Long convertDoubleToLong(double d)
static int readInt(char *buffer)
size_t MONITOR_EXT_WRAP_NAME() fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
Definition: io-over.c:260
#define SIZEOF_BYTE
Definition: Constants.hpp:69
static short readShort(char *buffer)
static void writeLong(char *buffer, int64_t ToWrite)
static double convertLongToDouble(Long l)
static void writeShort(char *buffer, short ToWrite)