Initial revision


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/network/Makefile.in b/network/Makefile.in
new file mode 100644
index 0000000..8aed303
--- /dev/null
+++ b/network/Makefile.in
@@ -0,0 +1,17 @@
+
+SRCS = TcpSocket.cxx
+
+OBJS = $(SRCS:.cxx=.o)
+
+DIR_CPPFLAGS = -I$(top_srcdir) @SOCKLEN_T_DEFINE@
+
+library = libnetwork.a
+
+all:: $(library)
+
+$(library): $(OBJS)
+	rm -f $(library)
+	$(AR) $(library) $(OBJS)
+	$(RANLIB) $(library)
+
+# followed by boilerplate.mk
diff --git a/network/Socket.h b/network/Socket.h
new file mode 100644
index 0000000..a08afe5
--- /dev/null
+++ b/network/Socket.h
@@ -0,0 +1,129 @@
+/* Copyright (C) 2002-2004 RealVNC Ltd.  All Rights Reserved.
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+// -=- Socket.h - abstract base-class for any kind of network stream/socket
+
+#ifndef __NETWORK_SOCKET_H__
+#define __NETWORK_SOCKET_H__
+
+#include <rdr/FdInStream.h>
+#include <rdr/FdOutStream.h>
+#include <rdr/Exception.h>
+
+namespace network {
+
+  class Socket {
+  public:
+    Socket(int fd)
+      : instream(new rdr::FdInStream(fd)),
+      outstream(new rdr::FdOutStream(fd)),
+      own_streams(true) {}
+    virtual ~Socket() {
+      if (own_streams) {
+        delete instream;
+        delete outstream;
+      }
+    }
+    rdr::FdInStream &inStream() {return *instream;}
+    rdr::FdOutStream &outStream() {return *outstream;}
+    int getFd() {return outstream->getFd();}
+    virtual void shutdown() = 0;
+
+    // information about this end of the socket
+    virtual char* getMyAddress() = 0; // a string e.g. "192.168.0.1"
+    virtual int getMyPort() = 0;
+    virtual char* getMyEndpoint() = 0; // <address>::<port>
+
+    // information about the remote end of the socket
+    virtual char* getPeerAddress() = 0; // a string e.g. "192.168.0.1"
+    virtual int getPeerPort() = 0;
+    virtual char* getPeerEndpoint() = 0; // <address>::<port>
+
+    // Is the remote end on the same machine?
+    virtual bool sameMachine() = 0;
+
+  protected:
+    Socket() : instream(0), outstream(0), own_streams(false) {}
+    Socket(rdr::FdInStream* i, rdr::FdOutStream* o, bool own)
+      : instream(i), outstream(o), own_streams(own) {}
+    rdr::FdInStream* instream;
+    rdr::FdOutStream* outstream;
+    bool own_streams;
+  };
+
+  class ConnectionFilter {
+  public:
+    virtual bool verifyConnection(Socket* s) = 0;
+    virtual bool queryUserAcceptConnection(Socket*) {return false;}
+  };
+
+  class SocketListener {
+  public:
+    SocketListener() : fd(0), filter(0) {}
+    virtual ~SocketListener() {}
+
+    // shutdown() stops the socket from accepting further connections
+    virtual void shutdown() = 0;
+
+    // accept() returns a new Socket object if there is a connection
+    // attempt in progress AND if the connection passes the filter
+    // if one is installed.  Otherwise, returns 0.
+    virtual Socket* accept() = 0;
+
+    void setFilter(ConnectionFilter* f) {filter = f;}
+    int getFd() {return fd;}
+  protected:
+    int fd;
+    ConnectionFilter* filter;
+  };
+
+  struct SocketException : public rdr::SystemException {
+    SocketException(const char* text, int err_) : rdr::SystemException(text, err_) {}
+  };
+
+  class SocketServer {
+  public:
+    virtual ~SocketServer() {}
+
+    // addClient() tells the server to manage the socket.
+    //   If the server can't manage the socket, it must shutdown() it.
+    virtual void addClient(network::Socket* sock) = 0;
+
+    // processSocketEvent() tells the server there is a socket read event.
+    //   If there is an error, or the socket has been closed/shutdown then
+    //   the server MUST delete the socket AND return false.
+    virtual bool processSocketEvent(network::Socket* sock) = 0;
+
+    // checkTimeouts() allows the server to check socket timeouts, etc.  The
+    // return value is the number of milliseconds to wait before
+    // checkTimeouts() should be called again.  If this number is zero then
+    // there is no timeout and checkTimeouts() should be called the next time
+    // an event occurs.
+    virtual int checkTimeouts() = 0;
+
+    // soonestTimeout() is a function to help work out the soonest of several
+    // timeouts.
+    static void soonestTimeout(int* timeout, int newTimeout) {
+      if (newTimeout && (!*timeout || newTimeout < *timeout))
+        *timeout = newTimeout;
+    }
+  };
+
+}
+
+#endif // __NETWORK_SOCKET_H__
diff --git a/network/TcpSocket.cxx b/network/TcpSocket.cxx
new file mode 100644
index 0000000..b536e67
--- /dev/null
+++ b/network/TcpSocket.cxx
@@ -0,0 +1,458 @@
+/* Copyright (C) 2002-2004 RealVNC Ltd.  All Rights Reserved.
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifdef WIN32
+//#include <io.h>
+#include <winsock2.h>
+#define errorNumber WSAGetLastError()
+#define snprintf _snprintf
+#else
+#define errorNumber errno
+#define closesocket close
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#endif
+
+#include <network/TcpSocket.h>
+#include <rfb/util.h>
+#include <rfb/LogWriter.h>
+
+#ifndef VNC_SOCKLEN_T
+#define VNC_SOCKLEN_T int
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((unsigned long)-1)
+#endif
+
+using namespace network;
+using namespace rdr;
+
+static rfb::LogWriter vlog("TcpSocket");
+
+
+void
+TcpSocket::initTcpSockets() {
+#ifdef WIN32
+  WORD requiredVersion = MAKEWORD(2,0);
+  WSADATA initResult;
+  
+  if (WSAStartup(requiredVersion, &initResult) != 0)
+    throw SocketException("unable to initialise Winsock2", errorNumber);
+#else
+  signal(SIGPIPE, SIG_IGN);
+#endif
+}
+
+// -=- TcpSocket
+
+TcpSocket::TcpSocket(int sock, bool close)
+  : Socket(new FdInStream(sock), new FdOutStream(sock), true), closeFd(close)
+{
+}
+
+TcpSocket::TcpSocket(const char *host, int port)
+  : closeFd(true)
+{
+  int sock;
+
+  // - Create a socket
+  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    throw SocketException("unable to create socket", errorNumber);
+
+#ifndef WIN32
+  // - By default, close the socket on exec()
+  fcntl(sock, F_SETFD, FD_CLOEXEC);
+#endif
+
+  // - Connect it to something
+
+  // Try processing the host as an IP address
+  struct sockaddr_in addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = inet_addr(host);
+  addr.sin_port = htons(port);
+  if ((int)addr.sin_addr.s_addr == -1) {
+    // Host was not an IP address - try resolving as DNS name
+    struct hostent *hostinfo;
+    hostinfo = gethostbyname(host);
+    if (hostinfo && hostinfo->h_addr) {
+      addr.sin_addr.s_addr = ((struct in_addr *)hostinfo->h_addr)->s_addr;
+    } else {
+      int e = errorNumber;
+      closesocket(sock);
+      throw SocketException("unable to resolve host by name", e);
+    }
+  }
+
+  // Attempt to connect to the remote host
+  if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
+    int e = errorNumber;
+    closesocket(sock);
+    throw SocketException("unable to connect to host", e);
+  }
+
+  int one = 1;
+  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+		 (char *)&one, sizeof(one)) < 0) {
+    int e = errorNumber;
+    closesocket(sock);
+    throw SocketException("unable to setsockopt TCP_NODELAY", e);
+  }
+
+  // Create the input and output streams
+  instream = new FdInStream(sock);
+  outstream = new FdOutStream(sock);
+  own_streams = true;
+}
+
+TcpSocket::~TcpSocket() {
+  if (closeFd)
+    closesocket(getFd());
+}
+
+char* TcpSocket::getMyAddress() {
+  struct sockaddr_in  info;
+  struct in_addr    addr;
+  VNC_SOCKLEN_T info_size = sizeof(info);
+
+  getsockname(getFd(), (struct sockaddr *)&info, &info_size);
+  memcpy(&addr, &info.sin_addr, sizeof(addr));
+
+  char* name = inet_ntoa(addr);
+  if (name) {
+    return rfb::strDup(name);
+  } else {
+    return rfb::strDup("");
+  }
+}
+
+int TcpSocket::getMyPort() {
+  return getSockPort(getFd());
+}
+
+char* TcpSocket::getMyEndpoint() {
+  rfb::CharArray address; address.buf = getMyAddress();
+  int port = getMyPort();
+
+  int buflen = strlen(address.buf) + 32;
+  char* buffer = new char[buflen];
+  sprintf(buffer, "%s::%d", address.buf, port);
+  return buffer;
+}
+
+char* TcpSocket::getPeerAddress() {
+  struct sockaddr_in  info;
+  struct in_addr    addr;
+  VNC_SOCKLEN_T info_size = sizeof(info);
+
+  getpeername(getFd(), (struct sockaddr *)&info, &info_size);
+  memcpy(&addr, &info.sin_addr, sizeof(addr));
+
+  char* name = inet_ntoa(addr);
+  if (name) {
+    return rfb::strDup(name);
+  } else {
+    return rfb::strDup("");
+  }
+}
+
+int TcpSocket::getPeerPort() {
+  struct sockaddr_in  info;
+  VNC_SOCKLEN_T info_size = sizeof(info);
+
+  getpeername(getFd(), (struct sockaddr *)&info, &info_size);
+  return ntohs(info.sin_port);
+}
+
+char* TcpSocket::getPeerEndpoint() {
+  rfb::CharArray address; address.buf = getPeerAddress();
+  int port = getPeerPort();
+
+  int buflen = strlen(address.buf) + 32;
+  char* buffer = new char[buflen];
+  sprintf(buffer, "%s::%d", address.buf, port);
+  return buffer;
+}
+
+bool TcpSocket::sameMachine() {
+  struct sockaddr_in peeraddr, myaddr;
+  VNC_SOCKLEN_T addrlen = sizeof(struct sockaddr_in);
+
+  getpeername(getFd(), (struct sockaddr *)&peeraddr, &addrlen);
+  getsockname(getFd(), (struct sockaddr *)&myaddr, &addrlen);
+
+  return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr);
+}
+
+void TcpSocket::shutdown()
+{
+  ::shutdown(getFd(), 2);
+}
+
+bool TcpSocket::isSocket(int sock)
+{
+  struct sockaddr_in info;
+  VNC_SOCKLEN_T info_size = sizeof(info);
+  return getsockname(sock, (struct sockaddr *)&info, &info_size) >= 0;
+}
+
+bool TcpSocket::isConnected(int sock)
+{
+  struct sockaddr_in info;
+  VNC_SOCKLEN_T info_size = sizeof(info);
+  return getpeername(sock, (struct sockaddr *)&info, &info_size) >= 0;
+}
+
+int TcpSocket::getSockPort(int sock)
+{
+  struct sockaddr_in info;
+  VNC_SOCKLEN_T info_size = sizeof(info);
+  if (getsockname(sock, (struct sockaddr *)&info, &info_size) < 0)
+    return 0;
+  return ntohs(info.sin_port);
+}
+
+
+TcpListener::TcpListener(int port, bool localhostOnly, int sock, bool close_)
+  : closeFd(close_)
+{
+  if (sock != -1) {
+    fd = sock;
+    return;
+  }
+
+  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    throw SocketException("unable to create listening socket", errorNumber);
+
+#ifndef WIN32
+  // - By default, close the socket on exec()
+  fcntl(sock, F_SETFD, FD_CLOEXEC);
+
+  int one = 1;
+  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+		 (const char *)&one, sizeof(one)) < 0) {
+    int e = errorNumber;
+    closesocket(fd);
+    throw SocketException("unable to create listening socket", e);
+  }
+#endif
+
+  // - Bind it to the desired port
+  struct sockaddr_in addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(port);
+  if (localhostOnly)
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  else
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+  if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+    int e = errorNumber;
+    closesocket(fd);
+    throw SocketException("unable to bind listening socket", e);
+  }
+
+  // - Set it to be a listening socket
+  if (listen(fd, 5) < 0) {
+    int e = errorNumber;
+    closesocket(fd);
+    throw SocketException("unable to set socket to listening mode", e);
+  }
+}
+
+TcpListener::~TcpListener() {
+  if (closeFd) closesocket(fd);
+}
+
+void TcpListener::shutdown()
+{
+#ifdef WIN32
+  closesocket(getFd());
+#else
+  ::shutdown(getFd(), 2);
+#endif
+}
+
+
+Socket*
+TcpListener::accept() {
+  int new_sock = -1;
+
+  // Accept an incoming connection
+  if ((new_sock = ::accept(fd, 0, 0)) < 0)
+    throw SocketException("unable to accept new connection", errorNumber);
+
+#ifndef WIN32
+  // - By default, close the socket on exec()
+  fcntl(new_sock, F_SETFD, FD_CLOEXEC);
+#endif
+
+  // Disable Nagle's algorithm
+  int one = 1;
+  if (setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY,
+   (char *)&one, sizeof(one)) < 0) {
+    int e = errorNumber;
+    closesocket(new_sock);
+    throw SocketException("unable to setsockopt TCP_NODELAY", e);
+  }
+
+  // Create the socket object & check connection is allowed
+  TcpSocket* s = new TcpSocket(new_sock);
+  if (filter && !filter->verifyConnection(s)) {
+    delete s;
+    return 0;
+  }
+  return s;
+}
+
+void TcpListener::getMyAddresses(std::list<char*>* result) {
+  const hostent* addrs = gethostbyname(0);
+  if (addrs == 0)
+    throw rdr::SystemException("gethostbyname", errorNumber);
+  if (addrs->h_addrtype != AF_INET)
+    throw rdr::Exception("getMyAddresses: bad family");
+  for (int i=0; addrs->h_addr_list[i] != 0; i++) {
+    const char* addrC = inet_ntoa(*((struct in_addr*)addrs->h_addr_list[i]));
+    char* addr = new char[strlen(addrC)+1];
+    strcpy(addr, addrC);
+    result->push_back(addr);
+  }
+}
+
+int TcpListener::getMyPort() {
+  return TcpSocket::getSockPort(getFd());
+}
+
+
+TcpFilter::TcpFilter(const char* spec) {
+  rfb::CharArray tmp;
+  tmp.buf = rfb::strDup(spec);
+  while (tmp.buf) {
+    rfb::CharArray first;
+    rfb::strSplit(tmp.buf, ',', &first.buf, &tmp.buf);
+    if (strlen(first.buf))
+      filter.push_back(parsePattern(first.buf));
+  }
+}
+
+TcpFilter::~TcpFilter() {
+}
+
+
+static bool
+patternMatchIP(const TcpFilter::Pattern& pattern, const char* value) {
+  unsigned long address = inet_addr(value);
+  if (address == INADDR_NONE) return false;
+  return ((pattern.address & pattern.mask) == (address & pattern.mask));
+}
+
+bool
+TcpFilter::verifyConnection(Socket* s) {
+  rfb::CharArray name;
+
+  name.buf = s->getPeerAddress();
+  std::list<TcpFilter::Pattern>::iterator i;
+  for (i=filter.begin(); i!=filter.end(); i++) {
+    if (patternMatchIP(*i, name.buf)) {
+      switch ((*i).action) {
+      case Accept:
+        vlog.debug("ACCEPT %s", name.buf);
+        return true;
+      case Query:
+        vlog.debug("QUERY %s", name.buf);
+        return queryUserAcceptConnection(s);
+      case Reject:
+        vlog.debug("REJECT %s", name.buf);
+        return false;
+      }
+    }
+  }
+
+  vlog.debug("[REJECT] %s", name.buf);
+  return false;
+}
+
+
+TcpFilter::Pattern TcpFilter::parsePattern(const char* p) {
+  TcpFilter::Pattern pattern;
+
+  bool expandMask = false;
+  rfb::CharArray addr, mask;
+
+  if (rfb::strSplit(&p[1], '/', &addr.buf, &mask.buf)) {
+    if (rfb::strContains(mask.buf, '.')) {
+      pattern.mask = inet_addr(mask.buf);
+    } else {
+      pattern.mask = atoi(mask.buf);
+      expandMask = true;
+    }
+  } else {
+    pattern.mask = 32;
+    expandMask = true;
+  }
+  if (expandMask) {
+    unsigned long expanded = 0;
+    // *** check endianness!
+    for (int i=0; i<(int)pattern.mask; i++)
+      expanded |= 1<<(31-i);
+    pattern.mask = htonl(expanded);
+  }
+
+  pattern.address = inet_addr(addr.buf) & pattern.mask;
+  if ((pattern.address == INADDR_NONE) ||
+      (pattern.address == 0)) pattern.mask = 0;
+
+  switch(p[0]) {
+  case '+': pattern.action = TcpFilter::Accept; break;
+  case '-': pattern.action = TcpFilter::Reject; break;
+  case '?': pattern.action = TcpFilter::Query; break;
+  };
+
+  return pattern;
+}
+
+char* TcpFilter::patternToStr(const TcpFilter::Pattern& p) {
+  in_addr tmp;
+  rfb::CharArray addr, mask;
+  tmp.s_addr = p.address;
+  addr.buf = rfb::strDup(inet_ntoa(tmp));
+  tmp.s_addr = p.mask;
+  mask.buf = rfb::strDup(inet_ntoa(tmp));
+  char* result = new char[strlen(addr.buf)+1+strlen(mask.buf)+1+1];
+  switch (p.action) {
+  case Accept: result[0] = '+'; break;
+  case Reject: result[0] = '-'; break;
+  case Query: result[0] = '?'; break;
+  };
+  result[1] = 0;
+  strcat(result, addr.buf);
+  strcat(result, "/");
+  strcat(result, mask.buf);
+  return result;
+}
diff --git a/network/TcpSocket.h b/network/TcpSocket.h
new file mode 100644
index 0000000..9533340
--- /dev/null
+++ b/network/TcpSocket.h
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002-2004 RealVNC Ltd.  All Rights Reserved.
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+// -=- TcpSocket.h - base-class for TCP stream sockets.
+//     This header also defines the TcpListener class, used
+//     to listen for incoming socket connections over TCP
+//
+//     NB: Any file descriptors created by the TcpSocket or
+//     TcpListener classes are close-on-exec if the OS supports
+//     it.  TcpSockets initialised with a caller-supplied fd
+//     are NOT set to close-on-exec.
+
+#ifndef __NETWORK_TCP_SOCKET_H__
+#define __NETWORK_TCP_SOCKET_H__
+
+#include <network/Socket.h>
+
+#include <list>
+
+namespace network {
+
+  class TcpSocket : public Socket {
+  public:
+    TcpSocket(int sock, bool close=true);
+    TcpSocket(const char *name, int port);
+    virtual ~TcpSocket();
+
+    virtual char* getMyAddress();
+    virtual int getMyPort();
+    virtual char* getMyEndpoint();
+
+    virtual char* getPeerAddress();
+    virtual int getPeerPort();
+    virtual char* getPeerEndpoint();
+    virtual bool sameMachine();
+
+    virtual void shutdown();
+
+    static void initTcpSockets();
+
+    static bool isSocket(int sock);
+    static bool isConnected(int sock);
+    static int getSockPort(int sock);
+  private:
+    bool closeFd;
+  };
+
+  class TcpListener : public SocketListener {
+  public:
+    TcpListener(int port, bool localhostOnly=false, int sock=-1,
+                bool close=true);
+    virtual ~TcpListener();
+
+    virtual void shutdown();
+    virtual Socket* accept();
+
+    void getMyAddresses(std::list<char*>* addrs);
+    int getMyPort();
+
+  private:
+    bool closeFd;
+  };
+
+  class TcpFilter : public ConnectionFilter {
+  public:
+    TcpFilter(const char* filter);
+    virtual ~TcpFilter();
+
+    virtual bool verifyConnection(Socket* s);
+
+    typedef enum {Accept, Reject, Query} Action;
+    struct Pattern {
+      Action action;
+      unsigned long address;
+      unsigned long mask;
+    };
+    static Pattern parsePattern(const char* s);
+    static char* patternToStr(const Pattern& p);
+  protected:
+    std::list<Pattern> filter;
+  };
+
+}
+
+#endif // __NETWORK_TCP_SOCKET_H__
diff --git a/network/msvcwarning.h b/network/msvcwarning.h
new file mode 100644
index 0000000..e93f2bb
--- /dev/null
+++ b/network/msvcwarning.h
@@ -0,0 +1,18 @@
+/* Copyright (C) 2002-2003 RealVNC Ltd.  All Rights Reserved.
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+#pragma warning( disable : 4800 ) // forcing bool 'true' or 'false'
diff --git a/network/network.dsp b/network/network.dsp
new file mode 100644
index 0000000..4290700
--- /dev/null
+++ b/network/network.dsp
@@ -0,0 +1,129 @@
+# Microsoft Developer Studio Project File - Name="network" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=network - Win32 Debug Unicode
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "network.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "network.mak" CFG="network - Win32 Debug Unicode"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "network - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "network - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "network - Win32 Debug Unicode" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "network - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O1 /I ".." /FI"msvcwarning.h" /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "network - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "network - Win32 Debug Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "network___Win32_Debug_Unicode"
+# PROP BASE Intermediate_Dir "network___Win32_Debug_Unicode"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_Unicode"
+# PROP Intermediate_Dir "Debug_Unicode"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_LIB" /D "_DEBUG" /D "WIN32" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF 
+
+# Begin Target
+
+# Name "network - Win32 Release"
+# Name "network - Win32 Debug"
+# Name "network - Win32 Debug Unicode"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\TcpSocket.cxx
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TcpSocket.h
+# End Source File
+# End Group
+# End Target
+# End Project