// Module: Log4CPLUS
// File: socket-win32.cxx
// Created: 4/2003
// Author: Tad E. Smith
//
//
// Copyright (C) Tad E. Smith All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: socket-win32.cxx,v $
// Revision 1.7 2003/12/07 07:26:58 tcsmith
// Fixed the read() method so that it will call recv() multiple times if it only receives a
// partial message.
//
// Revision 1.6 2003/09/28 03:48:14 tcsmith
// Removed compilation warning.
//
// Revision 1.5 2003/09/10 06:45:47 tcsmith
// Changed connectSocket() to check for INVALID_SOCKET.
//
// Revision 1.4 2003/08/15 06:34:55 tcsmith
// Added some casts to remove compilation warnings.
//
// Revision 1.3 2003/08/08 06:02:36 tcsmith
// Added #pragma statement.
//
// Revision 1.2 2003/05/21 22:16:00 tcsmith
// Fixed compiler warning: "conversion from 'size_t' to 'int', possible loss
// of data".
//
// Revision 1.1 2003/05/04 07:25:16 tcsmith
// Initial version.
//
#include <log4cplus/helpers/socket.h>
#include <log4cplus/helpers/loglog.h>
#pragma comment(lib, "ws2_32.lib")
using namespace log4cplus;
using namespace log4cplus::helpers;
/////////////////////////////////////////////////////////////////////////////
// file LOCAL Classes
/////////////////////////////////////////////////////////////////////////////
namespace {
class WinSockInitializer {
public:
WinSockInitializer() {
WSAStartup(MAKEWORD(1, 1), &wsa);
}
~WinSockInitializer() {
WSACleanup();
}
WSADATA wsa;
} winSockInitializer;
}
/////////////////////////////////////////////////////////////////////////////
// Global Methods
/////////////////////////////////////////////////////////////////////////////
SOCKET_TYPE
log4cplus::helpers::openSocket(unsigned short port, SocketState& state)
{
SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET) {
return sock;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if(bind(sock, (struct sockaddr*)&server, sizeof(server)) != 0) {
return INVALID_SOCKET;
}
if(::listen(sock, 10) != 0) {
return INVALID_SOCKET;
}
state = ok;
return sock;
}
SOCKET_TYPE
log4cplus::helpers::connectSocket(const log4cplus::tstring& hostn,
unsigned short port, SocketState& state)
{
SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET) {
return INVALID_SOCKET;
}
unsigned long ip = INADDR_NONE;
struct hostent *hp = ::gethostbyname( LOG4CPLUS_TSTRING_TO_STRING(hostn).c_str() );
if(hp == 0 || hp->h_addrtype != AF_INET) {
ip = inet_addr( LOG4CPLUS_TSTRING_TO_STRING(hostn).c_str() );
if(ip == INADDR_NONE) {
state = bad_address;
return INVALID_SOCKET;
}
}
struct sockaddr_in insock;
insock.sin_port = htons(port);
insock.sin_family = AF_INET;
if(hp != 0) {
memcpy(&insock.sin_addr, hp->h_addr, sizeof insock.sin_addr);
}
else {
insock.sin_addr.S_un.S_addr = ip;
}
int retval;
while( (retval = ::connect(sock, (struct sockaddr*)&insock, sizeof(insock))) == -1
&& (WSAGetLastError() == WSAEINTR))
;
if(retval == SOCKET_ERROR) {
::closesocket(sock);
return INVALID_SOCKET;
}
int enabled = 1;
if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enabled, sizeof(enabled)) != 0) {
::closesocket(sock);
return INVALID_SOCKET;
}
state = ok;
return sock;
}
SOCKET_TYPE
log4cplus::helpers::acceptSocket(SOCKET_TYPE sock, SocketState& /*state*/)
{
return ::accept(sock, NULL, NULL);
}
int
log4cplus::helpers::closeSocket(SOCKET_TYPE sock)
{
return ::closesocket(sock);
}
size_t
log4cplus::helpers::read(SOCKET_TYPE sock, SocketBuffer& buffer)
{
size_t res, read = 0;
do
{
res = ::recv(sock,
buffer.getBuffer() + read,
static_cast<int>(buffer.getMaxSize() - read),
0);
if( res <= 0 ) {
return res;
}
read += res;
} while( read < buffer.getMaxSize() );
return read;
}
size_t
log4cplus::helpers::write(SOCKET_TYPE sock, const SocketBuffer& buffer)
{
return ::send(sock, buffer.getBuffer(), static_cast<int>(buffer.getSize()), 0);
}
syntax highlighted by Code2HTML, v. 0.9.1