MFEM  v3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
socketstream.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.googlecode.com.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #include "socketstream.hpp"
13 
14 #include <cstring> // memset, memcpy
15 #ifndef _WIN32
16 #include <netdb.h> // gethostbyname
17 #include <arpa/inet.h> // htons
18 #include <sys/types.h> // socket, setsockopt, connect, recv, send
19 #include <sys/socket.h> // socket, setsockopt, connect, recv, send
20 #include <unistd.h> // close
21 #include <netinet/in.h> // sockaddr_in
22 #define closesocket (::close)
23 #else
24 #include <winsock.h>
25 typedef int ssize_t;
26 // Link with ws2_32.lib
27 #pragma comment(lib, "ws2_32.lib")
28 #endif
29 
30 namespace mfem
31 {
32 
33 int socketbuf::attach(int sd)
34 {
35  int old_sd = socket_descriptor;
36  pubsync();
37  socket_descriptor = sd;
38  setg(NULL, NULL, NULL);
39  setp(obuf, obuf + buflen);
40  return old_sd;
41 }
42 
43 int socketbuf::open(const char hostname[], int port)
44 {
45  struct sockaddr_in sa;
46  struct hostent *hp;
47 
48  close();
49  setg(NULL, NULL, NULL);
50  setp(obuf, obuf + buflen);
51 
52  hp = gethostbyname(hostname);
53  if (hp == NULL)
54  {
55  socket_descriptor = -3;
56  return -1;
57  }
58  memset(&sa, 0, sizeof(sa));
59  memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length);
60  sa.sin_family = hp->h_addrtype;
61  sa.sin_port = htons(port);
62  socket_descriptor = socket(hp->h_addrtype, SOCK_STREAM, 0);
63  if (socket_descriptor < 0)
64  return -1;
65  if (connect(socket_descriptor,
66  (const struct sockaddr *)&sa, sizeof(sa)) < 0)
67  {
68  closesocket(socket_descriptor);
69  socket_descriptor = -2;
70  return -1;
71  }
72  return 0;
73 }
74 
76 {
77  if (is_open())
78  {
79  pubsync();
80  int err = closesocket(socket_descriptor);
81  socket_descriptor = -1;
82  return err;
83  }
84  return 0;
85 }
86 
88 {
89  ssize_t bw, n = pptr() - pbase();
90  // std::cout << "[socketbuf::sync n=" << n << ']' << std::endl;
91  while (n > 0)
92  {
93 #ifdef MSG_NOSIGNAL
94  bw = send(socket_descriptor, pptr() - n, n, MSG_NOSIGNAL);
95 #else
96  bw = send(socket_descriptor, pptr() - n, n, 0);
97 #endif
98  if (bw < 0)
99  {
100  setp(pptr() - n, obuf + buflen);
101  pbump(n);
102  return -1;
103  }
104  n -= bw;
105  }
106  setp(obuf, obuf + buflen);
107  return 0;
108 }
109 
110 socketbuf::int_type socketbuf::underflow()
111 {
112  // assuming (gptr() < egptr()) is false
113  ssize_t br = recv(socket_descriptor, ibuf, buflen, 0);
114  // std::cout << "[socketbuf::underflow br=" << br << ']'
115  // << std::endl;
116  if (br <= 0)
117  {
118  setg(NULL, NULL, NULL);
119  return traits_type::eof();
120  }
121  setg(ibuf, ibuf, ibuf + br);
122  return traits_type::to_int_type(*ibuf);
123 }
124 
125 socketbuf::int_type socketbuf::overflow(int_type c)
126 {
127  if (sync() < 0)
128  return traits_type::eof();
129  if (traits_type::eq_int_type(c, traits_type::eof()))
130  return traits_type::not_eof(c);
131  *pptr() = traits_type::to_char_type(c);
132  pbump(1);
133  return c;
134 }
135 
136 std::streamsize socketbuf::xsgetn(char_type *__s, std::streamsize __n)
137 {
138  // std::cout << "[socketbuf::xsgetn __n=" << __n << ']'
139  // << std::endl;
140  const std::streamsize bn = egptr() - gptr();
141  if (__n <= bn)
142  {
143  traits_type::copy(__s, gptr(), __n);
144  gbump(__n);
145  return __n;
146  }
147  traits_type::copy(__s, gptr(), bn);
148  setg(NULL, NULL, NULL);
149  std::streamsize remain = __n - bn;
150  char_type *end = __s + __n;
151  ssize_t br;
152  while (remain > 0)
153  {
154  br = recv(socket_descriptor, end - remain, remain, 0);
155  if (br <= 0)
156  return (__n - remain);
157  remain -= br;
158  }
159  return __n;
160 }
161 
162 std::streamsize socketbuf::xsputn(const char_type *__s, std::streamsize __n)
163 {
164  // std::cout << "[socketbuf::xsputn __n=" << __n << ']'
165  // << std::endl;
166  if (pptr() + __n <= epptr())
167  {
168  traits_type::copy(pptr(), __s, __n);
169  pbump(__n);
170  return __n;
171  }
172  if (sync() < 0)
173  return 0;
174  ssize_t bw;
175  std::streamsize remain = __n;
176  const char_type *end = __s + __n;
177  while (remain > buflen)
178  {
179 #ifdef MSG_NOSIGNAL
180  bw = send(socket_descriptor, end - remain, remain, MSG_NOSIGNAL);
181 #else
182  bw = send(socket_descriptor, end - remain, remain, 0);
183 #endif
184  if (bw < 0)
185  return (__n - remain);
186  remain -= bw;
187  }
188  if (remain > 0)
189  {
190  traits_type::copy(pptr(), end - remain, remain);
191  pbump(remain);
192  }
193  return __n;
194 }
195 
196 
198 {
199  listen_socket = socket(PF_INET, SOCK_STREAM, 0); // tcp socket
200  if (listen_socket < 0)
201  {
202  return;
203  }
204  int on = 1;
205  if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
206  (char *)(&on), sizeof(on)) < 0)
207  {
208  closesocket(listen_socket);
209  listen_socket = -2;
210  return;
211  }
212  struct sockaddr_in sa;
213  memset(&sa, 0, sizeof(sa));
214  sa.sin_family = AF_INET;
215  sa.sin_port = htons(port);
216  sa.sin_addr.s_addr = INADDR_ANY;
217  if (bind(listen_socket, (const struct sockaddr *)&sa, sizeof(sa)))
218  {
219  closesocket(listen_socket);
220  listen_socket = -3;
221  return;
222  }
223  const int backlog = 4;
224  if (listen(listen_socket, backlog) < 0)
225  {
226  closesocket(listen_socket);
227  listen_socket = -4;
228  return;
229  }
230 }
231 
233 {
234  if (!good())
235  return 0;
236  int err = closesocket(listen_socket);
237  listen_socket = -1;
238  return err;
239 }
240 
242 {
243  if (!good())
244  return -1;
245  int socketd = ::accept(listen_socket, NULL, NULL);
246  if (socketd >= 0)
247  {
248  sockstr.rdbuf()->close();
249  sockstr.rdbuf()->attach(socketd);
250  }
251  return socketd;
252 }
253 
254 }
virtual std::streamsize xsgetn(char_type *__s, std::streamsize __n)
socketbuf * rdbuf()
int accept(socketstream &sockstr)
virtual int_type underflow()
virtual int_type overflow(int_type c=traits_type::eof())
int attach(int sd)
int ssize_t
Definition: isockstream.cpp:25
virtual int sync()
virtual std::streamsize xsputn(const char_type *__s, std::streamsize __n)
int open(const char hostname[], int port)