1 // Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11
12 #include "isockstream.hpp"
13 #include "globals.hpp"
14 #include <iostream>
15 #include <cstring>
16 #include <cstdlib>
17 #include <errno.h>
18 #ifndef _WIN32
19 #include <netinet/in.h>
20 #include <netdb.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <unistd.h>
24 #else
25 #include <winsock.h>
26 typedef int ssize_t;
27 typedef int socklen_t;
28 #define close closesocket
29 // Link with ws2_32.lib
30 #pragma comment(lib, "ws2_32.lib")
31 #endif
32
33 using namespace std;
34
35 namespace mfem
36 {
37
isockstream(int port)38 isockstream::isockstream(int port)
39 {
40 portnum = port;
41
42 if ( (portID = establish()) < 0)
43 mfem::out << "Server couldn't be established on port "
44 << portnum << endl;
45 Buf = NULL;
46 }
47
establish()48 int isockstream::establish()
49 {
50 // char myname[129];
51 char myname[] = "localhost";
52 int port;
53 struct sockaddr_in sa;
54 struct hostent *hp;
55
56 memset(&sa, 0, sizeof(struct sockaddr_in));
57 // gethostname(myname, 128);
58 hp= gethostbyname(myname);
59
60 if (hp == NULL)
61 {
62 mfem::err << "isockstream::establish(): gethostbyname() failed!\n"
63 << "isockstream::establish(): gethostname() returned: '"
64 << myname << "'" << endl;
65 error = 1;
66 return (-1);
67 }
68
69 sa.sin_family= hp->h_addrtype;
70 sa.sin_port= htons(portnum);
71
72 if ((port = socket(AF_INET, SOCK_STREAM, 0)) < 0)
73 {
74 mfem::err << "isockstream::establish(): socket() failed!" << endl;
75 error = 2;
76 return (-1);
77 }
78
79 int on=1;
80 setsockopt(port, SOL_SOCKET, SO_REUSEADDR, (char *)(&on), sizeof(on));
81
82 if (bind(port,(const sockaddr*)&sa,(socklen_t)sizeof(struct sockaddr_in)) < 0)
83 {
84 mfem::err << "isockstream::establish(): bind() failed!" << endl;
85 close(port);
86 error = 3;
87 return (-1);
88 }
89
90 listen(port, 4);
91 error = 0;
92 return (port);
93 }
94
read_data(int s,char * buf,int n)95 int isockstream::read_data(int s, char *buf, int n)
96 {
97 int bcount; // counts bytes read
98 int br; // bytes read this pass
99
100 bcount= 0;
101 while (bcount < n) // loop until full buffer
102 {
103 if ((br = recv(s, buf, n - bcount, 0)) > 0)
104 {
105 bcount += br; // increment byte counter
106 buf += br; // move buffer ptr for next read
107 }
108 else if (br < 0) // signal an error to the caller
109 {
110 error = 4;
111 return (-1);
112 }
113 }
114 return (bcount);
115 }
116
receive(std::istringstream ** in)117 void isockstream::receive(std::istringstream **in)
118 {
119 int size;
120 char length[32];
121
122 if ((*in) != NULL)
123 {
124 delete (*in), *in = NULL;
125 }
126
127 if (portID == -1)
128 {
129 return;
130 }
131
132 if ((socketID = accept(portID, NULL, NULL)) < 0)
133 {
134 mfem::out << "Server failed to accept connection." << endl;
135 error = 5;
136 return;
137 }
138
139 if (recv(socketID, length, 32, 0) < 0)
140 {
141 error = 6;
142 return;
143 }
144 size = atoi(length);
145
146 if (Buf != NULL)
147 {
148 delete [] Buf;
149 }
150 Buf = new char[size+1];
151 if (size != read_data(socketID, Buf, size))
152 {
153 mfem::out << "Not all the data has been read" << endl;
154 }
155 #ifdef DEBUG
156 else
157 {
158 mfem::out << "Reading " << size << " bytes is successful" << endl;
159 }
160 #endif
161 Buf[size] = '\0';
162
163 close(socketID);
164 (*in) = new istringstream(Buf);
165 }
166
~isockstream()167 isockstream::~isockstream()
168 {
169 if (Buf != NULL)
170 {
171 delete [] Buf;
172 }
173 if (portID != -1)
174 {
175 close(portID);
176 }
177 }
178
179 }
180