tesseract v5.3.3.20231005
tesseract::SVNetwork Class Reference

#include <svutil.h>

Public Member Functions

 SVNetwork (const char *hostname, int port)
 Set up a connection to hostname on port. More...
 
 ~SVNetwork ()
 Destructor. More...
 
void Send (const char *msg)
 Put a message in the messagebuffer to the server and try to send it. More...
 
char * Receive ()
 
void Close ()
 Close the connection to the server. More...
 
void Flush ()
 Flush the buffer. More...
 

Detailed Description

The SVNetwork class takes care of the remote connection for ScrollView This means setting up and maintaining a remote connection, sending and receiving messages and closing the connection. It is designed to work on both Linux and Windows.

Definition at line 71 of file svutil.h.

Constructor & Destructor Documentation

◆ SVNetwork()

tesseract::SVNetwork::SVNetwork ( const char *  hostname,
int  port 
)

Set up a connection to hostname on port.

Definition at line 275 of file svutil.cpp.

275 {
276 msg_buffer_in_ = new char[kMaxMsgSize + 1];
277 msg_buffer_in_[0] = '\0';
278
279 buffer_ptr_ = nullptr;
280
281 struct addrinfo *addr_info = nullptr;
282 auto port_string = std::to_string(port);
283# ifdef _WIN32
284 // Initialize Winsock
285 WSADATA wsaData;
286 int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
287 if (iResult != 0) {
288 std::cerr << "WSAStartup failed: " << iResult << std::endl;
289 }
290# endif // _WIN32
291
292 if (getaddrinfo(hostname, port_string.c_str(), nullptr, &addr_info) != 0) {
293 std::cerr << "Error resolving name for ScrollView host "
294 << std::string(hostname) << ":" << port << std::endl;
295# ifdef _WIN32
296 WSACleanup();
297# endif // _WIN32
298 }
299
300 if (addr_info == nullptr) {
301 // Mark stream_ as invalid.
302 stream_ = -1;
303 } else {
304 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
305 addr_info->ai_protocol);
306 }
307
308 if (stream_ < 0) {
309 std::cerr << "Failed to open socket" << std::endl;
310 } else if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
311 // If server is not there, we will start a new server as local child
312 // process.
313 const char *scrollview_path = getenv("SCROLLVIEW_PATH");
314 if (scrollview_path == nullptr) {
315# ifdef SCROLLVIEW_PATH
316# define _STR(a) # a
317# define _XSTR(a) _STR(a)
318 scrollview_path = _XSTR(SCROLLVIEW_PATH);
319# undef _XSTR
320# undef _STR
321# else
322 scrollview_path = ".";
323# endif
324 }
325 const char *prog = ScrollViewProg();
326 std::string command = ScrollViewCommand(scrollview_path);
327 SVSync::StartProcess(prog, command.c_str());
328
329 // Wait for server to show up.
330 // Note: There is no exception handling in case the server never turns up.
331
332 Close();
333 for (;;) {
334 stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
335 addr_info->ai_protocol);
336 if (stream_ >= 0) {
337 if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) == 0) {
338 break;
339 }
340
341 Close();
342
343 std::cout << "ScrollView: Waiting for server...\n";
344 std::this_thread::sleep_for(std::chrono::seconds(1));
345 }
346 }
347 }
348# ifdef _WIN32
349 // WSACleanup(); // This cause ScrollView windows is not displayed
350# endif // _WIN32
351 freeaddrinfo(addr_info);
352}
const int kMaxMsgSize
Definition: scrollview.cpp:46
static void StartProcess(const char *executable, const char *args)
Starts a new process.
Definition: svutil.cpp:67
void Close()
Close the connection to the server.
Definition: svutil.cpp:225

◆ ~SVNetwork()

tesseract::SVNetwork::~SVNetwork ( )

Destructor.

Definition at line 354 of file svutil.cpp.

354 {
355 Close();
356 delete[] msg_buffer_in_;
357}

Member Function Documentation

◆ Close()

void tesseract::SVNetwork::Close ( )

Close the connection to the server.

Definition at line 225 of file svutil.cpp.

225 {
226# ifdef _WIN32
227 closesocket(stream_);
228# else
229 close(stream_);
230# endif
231 // Mark stream_ as invalid.
232 stream_ = -1;
233}

◆ Flush()

void tesseract::SVNetwork::Flush ( )

Flush the buffer.

Definition at line 170 of file svutil.cpp.

170 {
171 std::lock_guard<std::mutex> guard(mutex_send_);
172 while (!msg_buffer_out_.empty()) {
173 int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
174 msg_buffer_out_.erase(0, i);
175 }
176}

◆ Receive()

char * tesseract::SVNetwork::Receive ( )

Receive a message from the server. This will always return one line of char* (denoted by \n).

Definition at line 180 of file svutil.cpp.

180 {
181 char *result = nullptr;
182 if (buffer_ptr_ != nullptr) {
183 result = strtok_r(nullptr, "\n", &buffer_ptr_);
184 }
185
186 // This means there is something left in the buffer and we return it.
187 if (result != nullptr) {
188 return result;
189 // Otherwise, we read from the stream_.
190 } else {
191 buffer_ptr_ = nullptr;
192
193 // The timeout length is not really important since we are looping anyway
194 // until a new message is delivered.
195 struct timeval tv;
196 tv.tv_sec = 10;
197 tv.tv_usec = 0;
198
199 // Set the flags to return when the stream_ is ready to be read.
200 fd_set readfds;
201 FD_ZERO(&readfds);
202 FD_SET(stream_, &readfds);
203
204 int i = select(stream_ + 1, &readfds, nullptr, nullptr, &tv);
205
206 // The stream_ died.
207 if (i == 0) {
208 return nullptr;
209 }
210
211 // Read the message buffer.
212 i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);
213
214 // Server quit (0) or error (-1).
215 if (i <= 0) {
216 return nullptr;
217 }
218 msg_buffer_in_[i] = '\0';
219 // Setup a new string tokenizer.
220 return strtok_r(msg_buffer_in_, "\n", &buffer_ptr_);
221 }
222}

◆ Send()

void tesseract::SVNetwork::Send ( const char *  msg)

Put a message in the messagebuffer to the server and try to send it.

Definition at line 164 of file svutil.cpp.

164 {
165 std::lock_guard<std::mutex> guard(mutex_send_);
166 msg_buffer_out_.append(msg);
167}

The documentation for this class was generated from the following files: