OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimToolClient.cpp
Go to the documentation of this file.
1 //**************************************************************************************************
2 //
3 // OSSIM Open Source Geospatial Data Processing Library
4 // See top level LICENSE.txt file for license information
5 //
6 //**************************************************************************************************
7 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <netdb.h>
16 #include <iostream>
17 #include <fstream>
18 #include <sstream>
19 #ifdef _MSC_VER
20 #include <Windows.h>
21 #include <io.h>
22 #else
23 #include <unistd.h>
24 #endif
25 
26 using namespace std;
27 
28 #define MAX_BUF_LEN 4096
29 #define _DEBUG_ false
30 
32 : m_svrsockfd(-1),
33  m_buffer(new char[MAX_BUF_LEN])
34 {
35  ossimFilename tmpdir = "/tmp";
36 #ifdef _MSC_VER
37  if (GetTempPath(MAX_BUF_LEN, m_buffer))
38  tmpdir = m_buffer;
39 #endif
40  setProductFilePath(tmpdir);
41 }
42 
44 {
45  disconnect();
46 }
47 
49 {
50  bool success = true;
51 
52  if (m_svrsockfd < 0)
53  return success;
54 
55  // Need to send close request to server:
56  if (close(m_svrsockfd) < 0)
57  {
58  error("Error closing socket");
59  success = false;
60  }
61 
62  m_svrsockfd = -1;
63  return success;
64 }
65 
66 
67 void ossimToolClient::error(const char *msg)
68 {
69  perror(msg);
70 }
71 
72 
73 int ossimToolClient::connectToServer(char* hostname, char* portname)
74 {
75  m_svrsockfd = -1;
76  while (1)
77  {
78  // Consider port number in host URL:
79  ossimString host (hostname);
80  ossimString port;
81  if (portname)
82  port = portname;
83  else if (host.contains(":"))
84  {
85  port = host.after(":");
86  host = host.before(":");
87  }
88 
89  if (port.empty())
90  {
91  // Maybe implied port then '/':
92  port = host.after("/");
93  port = "/" + port;
94  host = host.before("/");
95  }
96 
97  // Establish full server address including port:
98  struct addrinfo hints;
99  memset(&hints, 0, sizeof hints); // make sure the struct is empty
100  hints.ai_family = AF_INET; // don't care IPv4 or IPv6
101  hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
102  hints.ai_canonname = host.stringDup(); // fill in my IP for me
103  struct addrinfo *res;
104  int failed = getaddrinfo(host.stringDup(), port.stringDup(), &hints, &res);
105  if (failed)
106  {
107  error(gai_strerror(failed));
108  break;
109  }
110 
111  // Create socket for this server by walking the linked list of available addresses:
112  struct addrinfo *server_info = res;
113  while (server_info)
114  {
115  m_svrsockfd =
116  socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol);
117  if (m_svrsockfd >= 0)
118  break;
119  server_info = server_info->ai_next;
120  }
121  if ((m_svrsockfd < 0) || (server_info == NULL))
122  {
123  error("Error opening socket");
124  break;
125  }
126 
127  // Connect to the server:portno:
128  struct sockaddr_in* serv_addr = (sockaddr_in*) server_info->ai_addr;
129  serv_addr->sin_family = AF_INET;
130  if (connect(m_svrsockfd,(struct sockaddr*) serv_addr, server_info->ai_addrlen) < 0)
131  {
132  error("ERROR connecting");
133  disconnect();
134  }
135 
136  break;
137  }
138  return m_svrsockfd;
139 }
140 
141 
142 bool ossimToolClient::execute(const char* command_spec)
143 {
144  // Clear previous file path of product filename:
145  if (!m_prodFilePath.isDir())
147 
148  if (command_spec == NULL)
149  return false;
150 
151  // Write command to the OSSIM tool server socket:
152  if (_DEBUG_) cout<<"ossimToolClient:"<<__LINE__<<" sending <"<<command_spec<<">..."<<endl; //TODO REMOVE DEBUG
153  int n = send(m_svrsockfd, command_spec, strlen(command_spec), 0);
154  if (n < 0)
155  {
156  error("ERROR writing to socket");
157  return false;
158  }
159  while (n < (int) strlen(command_spec))
160  {
161  // Partial send, try remainder of buffer:
162  if (_DEBUG_) cout<<"ossimToolClient:"<<__LINE__<<" sending <"<<&(command_spec[n])<<">..."<<endl; //TODO REMOVE DEBUG
163  int r = send(m_svrsockfd, &(command_spec[n]), strlen(command_spec)-n, 0);
164  if (r < 0)
165  {
166  error("ERROR writing to socket");
167  return false;
168  }
169  n += r;
170  }
171 
172  // Process response from server. First read the response type. Can be either:
173  // "TEXT" -- only text is streamed
174  // "FILE" -- a file is treamed
175  // "MIXED" -- Both file and text
176  // "ERROR" -- only text with error message. No product generated.
177  // "ADIOS" -- Server acknowledges disconnect
178  bool success = false;
179  memset(m_buffer, 0, MAX_BUF_LEN);
180  if (_DEBUG_) cout<<"ossimToolClient:"<<__LINE__<<" Waiting to recv"<<endl; //TODO REMOVE DEBUG
181  n = recv(m_svrsockfd, m_buffer, 5, 0);
182  if (_DEBUG_) cout<<"ossimToolClient:"<<__LINE__<<" Received <"<<m_buffer<<">"<<endl; //TODO REMOVE DEBUG
183  if (n < 0)
184  {
185  error("ERROR reading from socket");
186  return false;
187  }
188  ossimString response (string(m_buffer, n));
189  if (response.contains("TEXT"))
190  success = receiveText();
191  else if (response.contains("FILE"))
192  success = receiveFile();
193  else if (response.contains("MIXED"))
194  success = receiveText() && receiveFile();
195  else if (response.contains("ERROR"))
196  receiveText(); // success = false;
197  else if (response.contains("ADIOS"))
198  error("Received unexpected disconnect message from server.");
199  else
200  error("Unknown type in response header");
201 
202  return success;
203 }
204 
205 
207 {
208  int n = MAX_BUF_LEN;
210  while (n == MAX_BUF_LEN)
211  {
212  memset(m_buffer, 0, MAX_BUF_LEN);
213  if (_DEBUG_) cout<<"ossimToolClient:"<<__LINE__<<" Waiting to recv"<<endl; //TODO REMOVE DEBUG
214  n = recv(m_svrsockfd, m_buffer, MAX_BUF_LEN, 0);
215  if (_DEBUG_) cout<<"ossimToolClient:"<<__LINE__<<" Received <"<<m_buffer<<">"<<endl; //TODO REMOVE DEBUG
216  if (n < 0)
217  {
218  error("ERROR reading from socket");
219  return false;
220  }
222  }
223  if (!acknowledgeRcv())
224  return false;
225 
226  printf("Text response:\n-----------------\n%s\n-----------------\n",m_textResponse.c_str());
227  return true;
228 }
229 
230 
232 {
233  ostringstream xmsg;
234  cout << "Server requesting file send. " <<endl;
235 
236  // Fetch the file size in bytes as the next message "SIZE: GGGMMMKKKBBB", (18 bytes)
237  if (!receiveText())
238  return false;
239  int filesize = m_textResponse.after("SIZE: ").toInt();
240  cout << "File size = " <<filesize<<endl;
241 
242  // Fetch the filename as next message "NAME: AAAAA...", (256 bytes)
243  if (!receiveText())
244  return false;
245  ossimFilename fileName (m_textResponse.after("NAME: "));
247  cout << "File name = " <<m_prodFilePath<<endl;
248 
249  // Open file for writing:
250  ofstream fout (m_prodFilePath.chars());
251  if (fout.fail())
252  {
253  xmsg <<"ERROR opening output file: <"<<m_prodFilePath<<">"<<ends;
254  error(xmsg.str().c_str());
255  return false;
256  }
257 
258  memset(m_buffer, 0, MAX_BUF_LEN);
259  int n = MAX_BUF_LEN;
260  int numBytes = 0;
261  while ((n == MAX_BUF_LEN) && (numBytes < filesize))
262  {
263  n = recv(m_svrsockfd, m_buffer, MAX_BUF_LEN, 0);
264  if (n < 0)
265  {
266  error("ERROR reading from socket");
267  return false;
268  }
269  fout.write(m_buffer, n);
270  if (fout.fail())
271  {
272  error("ERROR on file write().");
273  return false;
274  }
275  numBytes += n;
276  }
277 
278  if (!acknowledgeRcv())
279  return false;
280 
281  cout<<"\nossim-client: Received and wrote "<<numBytes<<" bytes to: <"<<m_prodFilePath<<">."<<endl;;
282  fout.close();
283 
284  return true;
285 }
286 
287 
289 {
290  if (_DEBUG_) cout<<"ossimToolClient:"<<__LINE__<<" sending \"ok_to_send\"..."<<endl; //TODO REMOVE DEBUG
291  int r = send(m_svrsockfd, "ok_to_send", 11, 0);
292  if (r < 0)
293  {
294  error("ERROR writing to socket");
295  return false;
296  }
297  if (_DEBUG_) cout << "Receive acknowledged."<<endl;
298  return true;
299 }
300 
301 
302 bool ossimToolClient::setProductFilePath(const char* filepath)
303 {
304  if (filepath == NULL)
305  m_prodFilePath = "./";
306  else
307  m_prodFilePath = filepath;
308 
309  ostringstream xmsg;
311  {
312  xmsg <<"ERROR creating output directory: <"<<m_prodFilePath<<">"<<ends;
313  error(xmsg.str().c_str());
314  }
315  else if (!m_prodFilePath.isWriteable())
316  {
317  xmsg <<"ERROR output directory: <"<<m_prodFilePath<<"> is not writable."<<ends;
318  error(xmsg.str().c_str());
319  }
320  return true;
321 }
void clear()
Erases the entire container.
Definition: ossimString.h:432
ossimString before(const ossimString &str, std::string::size_type pos=0) const
METHOD: before(str, pos) Returns string beginning at pos and ending one before the token str If strin...
bool isWriteable() const
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
~ossimToolClient()
Closes any open connections.
bool contains(char aChar) const
Definition: ossimString.h:58
bool execute(const char *command_spec)
Executes OSSIM tool command with options.
char * stringDup() const
bool isDir() const
const ossimString & append(const ossimString &s)
Definition: ossimString.h:831
#define MAX_BUF_LEN
bool exists() const
os2<< "> n<< " > nendobj n
const char * chars() const
For backward compatibility.
Definition: ossimString.h:77
bool setProductFilePath(const char *filepath)
Sets the local destination directory for file product.
int connectToServer(char *hostname, char *portname=NULL)
Accepts hostname and portname as a string.
if(yy_init)
#define _DEBUG_
ossimFilename m_prodFilePath
ossimString m_textResponse
ossimFilename dirCat(const ossimFilename &file) const
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
bool empty() const
Definition: ossimString.h:411
bool disconnect()
Closes connection to server and ready to connect again.
std::basic_ofstream< char > ofstream
Class for char output file streams.
Definition: ossimIosFwd.h:47
void error(const char *msg)
ossimString after(const ossimString &str, std::string::size_type pos=0) const
METHOD: after(str, pos) Returns string immediately after the token str.
bool createDirectory(bool recurseFlag=true, int perm=0775) const
ossimFilename path() const
int toInt() const