40 #include "blocxx/BLOCXX_config.h" 42 #if defined(BLOCXX_WIN32) 70 ::WSAStartup(MAKEWORD(2,2), &wsaData);
80 SockInitializer _sockInitializer;
84 _closeSocket(SOCKET& sockfd)
88 ::closesocket(sockfd);
97 SOCKET sd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
98 if (sd == SOCKET_ERROR)
104 INTERFACE_INFO interfaceList[20];
105 unsigned long nBytesReturned;
106 if (::WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &interfaceList,
107 sizeof(interfaceList), &nBytesReturned, 0, 0) != SOCKET_ERROR)
109 int nNumInterfaces = nBytesReturned /
sizeof(INTERFACE_INFO);
110 for (
int i = 0;
i < nNumInterfaces; ++
i)
112 u_long nFlags = interfaceList[
i].iiFlags;
116 ::memcpy(&addr, &(interfaceList[
i].iiAddress),
sizeof(addr));
117 if (!(nFlags & IFF_LOOPBACK))
141 String SocketBaseImpl::m_traceFileOut;
142 String SocketBaseImpl::m_traceFileIn;
147 SocketBaseImpl::waitForEvent(HANDLE eventArg,
int secsToTimeout)
149 DWORD timeout = (secsToTimeout != -1)
150 ? static_cast<DWORD>(secsToTimeout * 1000)
154 if(Socket::getShutDownMechanism() != NULL)
157 events[0] = Socket::getShutDownMechanism();
158 events[1] = eventArg;
160 DWORD index = ::WaitForMultipleObjects(
175 index -= WAIT_OBJECT_0;
179 ::ResetEvent(eventArg);
181 cc =
static_cast<int>(index);
187 switch(::WaitForSingleObject(eventArg, timeout))
190 ::ResetEvent(eventArg);
205 #pragma warning (push) 206 #pragma warning (disable: 4355) 209 SocketBaseImpl::SocketBaseImpl()
212 , m_isConnected(false)
217 , m_recvTimeoutExprd(false)
220 , m_out(&m_streamBuf)
221 , m_inout(&m_streamBuf)
222 , m_recvTimeout(Timeout::infinite)
223 , m_sendTimeout(Timeout::infinite)
224 , m_connectTimeout(Timeout::relative(0))
226 m_out.exceptions(std::ios::badbit);
227 m_inout.exceptions(std::ios::badbit);
228 m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
236 , m_isConnected(true)
238 , m_localAddress(SocketAddress::getAnyLocalHost())
239 , m_peerAddress(SocketAddress::allocEmptyAddress(addrType))
241 , m_recvTimeoutExprd(false)
244 , m_out(&m_streamBuf)
245 , m_inout(&m_streamBuf)
246 , m_recvTimeout(Timeout::infinite)
247 , m_sendTimeout(Timeout::infinite)
248 , m_connectTimeout(Timeout::relative(0))
252 m_out.exceptions(std::ios::badbit);
253 m_inout.exceptions(std::ios::badbit);
254 m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
262 , m_isConnected(false)
264 , m_localAddress(SocketAddress::getAnyLocalHost())
265 , m_peerAddress(addr)
267 , m_recvTimeoutExprd(false)
270 , m_out(&m_streamBuf)
271 , m_inout(&m_streamBuf)
272 , m_recvTimeout(Timeout::infinite)
273 , m_sendTimeout(Timeout::infinite)
274 , m_connectTimeout(Timeout::relative(0))
276 m_out.exceptions(std::ios::badbit);
277 m_inout.exceptions(std::ios::badbit);
278 m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
280 connect(m_peerAddress);
283 #pragma warning (pop) 296 ::CloseHandle(m_event);
304 st.sockfd = m_sockfd;
306 st.networkevents = FD_READ | FD_WRITE;
324 m_sockfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
328 Format(
"Failed to create a socket: %1",
333 WSANETWORKEVENTS networkEvents;
336 if(::WSAEventSelect(m_sockfd, m_event, FD_CONNECT) != 0)
339 Format(
"WSAEventSelect Failed: %1",
343 if (::connect(m_sockfd, addr.getNativeForm(), addr.getNativeFormSize())
346 int lastError = ::WSAGetLastError();
347 if (lastError != WSAEWOULDBLOCK && lastError != WSAEINPROGRESS)
349 _closeSocket(m_sockfd);
351 Format(
"Failed to connect to: %1: %2(%3)", addr.toString(),
355 TimeoutTimer timer(m_connectTimeout);
356 int tmoutval = timer.asDWORDMs();
362 if ((cc = waitForEvent(m_event, tmoutval)) < 1)
364 _closeSocket(m_sockfd);
369 "Sockets have been shutdown");
372 Format(
"Win32SocketBaseImpl connection" 373 " timed out. Timeout val = %1",
377 "connect() wait failed: %1(%2)",
384 if (::WSAEnumNetworkEvents(m_sockfd, m_event, &networkEvents)
387 _closeSocket(m_sockfd);
389 Format(
"SocketBaseImpl::connect()" 390 " failed getting network events: %1(%2)",
396 if (networkEvents.lNetworkEvents & FD_CONNECT)
399 if (networkEvents.iErrorCode[FD_CONNECT_BIT])
401 ::WSASetLastError(networkEvents.iErrorCode[FD_CONNECT_BIT]);
402 _closeSocket(m_sockfd);
404 Format(
"SocketBaseImpl::connect() failed: %1(%2)",
414 if(::WSAEventSelect(m_sockfd, m_event, 0) != 0)
416 _closeSocket(m_sockfd);
418 Format(
"Resetting socket with WSAEventSelect Failed: %1",
422 ::ioctlsocket(m_sockfd, FIONBIO, &ioctlarg);
424 m_isConnected =
true;
426 m_peerAddress = addr;
439 m_in.clear(ios::eofbit);
443 m_out.clear(ios::eofbit);
447 m_inout.clear(ios::eofbit);
451 _closeSocket(m_sockfd);
452 m_isConnected =
false;
461 ::memset(&addr, 0,
sizeof(addr));
463 bool gotAddr =
false;
468 if (::getsockname(m_sockfd,
469 reinterpret_cast<struct sockaddr*>(&addr), &len) != SOCKET_ERROR)
471 m_localAddress.assignFromNativeForm(&addr, len);
473 else if (getAddrFromIface(addr) == 0)
476 m_localAddress.assignFromNativeForm(&addr, len);
480 if (::getpeername(m_sockfd, reinterpret_cast<struct sockaddr*>(&addr),
481 &len) != SOCKET_ERROR)
483 m_peerAddress.assignFromNativeForm(&addr, len);
486 else if (getAddrFromIface(addr) == 0)
488 m_localAddress.assignFromNativeForm(&addr, len);
498 bool isError =
false;
501 isError = waitForOutput(m_sendTimeout);
508 rc = writeAux(dataOut, dataOutLen);
509 if (!m_traceFileOut.empty() && rc > 0)
512 ofstream traceFile(m_traceFileOut.c_str(), std::ios::app);
515 BLOCXX_THROW(IOException,
"Failed opening socket dump file");
517 if (!traceFile.write(static_cast<const char*>(dataOut), rc))
519 BLOCXX_THROW(IOException,
"Failed writing to socket dump");
522 ofstream comboTraceFile(String(m_traceFileOut +
"Combo").c_str(), std::ios::app);
525 BLOCXX_THROW(IOException,
"Failed opening socket dump file");
527 comboTraceFile <<
"\n--->Out " << rc <<
" bytes<---\n";
528 if (!comboTraceFile.write(static_cast<const char*>(dataOut), rc))
530 BLOCXX_THROW(IOException,
"Failed writing to socket dump");
539 if (rc < 0 && errorAsException)
550 bool isError =
false;
553 isError = waitForInput(m_recvTimeout);
560 rc = readAux(dataIn, dataInLen);
561 if (!m_traceFileIn.empty() && rc > 0)
564 ofstream traceFile(m_traceFileIn.c_str(), std::ios::app);
569 if (!traceFile.write(reinterpret_cast<const char*>(dataIn), rc))
571 BLOCXX_THROW(IOException,
"Failed writing to socket dump");
574 ofstream comboTraceFile(String(m_traceFileOut +
"Combo").c_str(), std::ios::app);
577 BLOCXX_THROW(IOException,
"Failed opening socket dump file");
579 comboTraceFile <<
"\n--->In " << rc <<
" bytes<---\n";
580 if (!comboTraceFile.write(reinterpret_cast<const char*>(dataIn), rc))
582 BLOCXX_THROW(IOException,
"Failed writing to socket dump");
593 if (errorAsException)
605 m_recvTimeoutExprd =
true;
609 m_recvTimeoutExprd =
false;
643 m_traceFileOut = out;
649 #endif // #if defined(BLOCXX_WIN32) static void setDumpFiles(const String &in, const String &out)
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(), it throws an AssertionException.
int write(const void *dataOut, int dataOutLen, ErrorAction errorAsException=E_RETURN_ON_ERROR)
Write a specified number of bytes to the device that is exposing the IOIFC interface.
bool waitForOutput(const Timeout &timeout)
virtual void disconnect()
String lastErrorMsg(bool socketError)
virtual bool waitForInput(const Timeout &timeout)
std::iostream & getIOStream()
int read(void *dataIn, int dataInLen, ErrorAction errorAsException=E_RETURN_ON_ERROR)
Read a specified number of bytes from the device that is exposing the IOIFC interface.
Select_t getSelectObj() const
std::ostream & getOutputStream()
sockaddr_in InetSocketAddress_t
std::istream & getInputStream()
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
int waitForIO(SocketHandle_t fd, int timeOutSecs, SocketFlags::EWaitDirectionFlag waitFlag)
Wait for input or output on a socket.
virtual void connect(const SocketAddress &addr)
virtual ~SocketBaseImpl()