Initial checkin of OOPHM plugins into trunk.  Testing of non-XPCOM plugins
is still required, and more platforms need to be built.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5868 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/common/Socket.h b/plugins/common/Socket.h
new file mode 100644
index 0000000..90298f6
--- /dev/null
+++ b/plugins/common/Socket.h
@@ -0,0 +1,170 @@
+#ifndef _H_Socket
+#define _H_Socket
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Platform.h"
+#include "Debug.h"
+
+#include <string>
+
+#ifdef _WINDOWS
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+/**
+ * Encapsulates platform dependencies regarding buffered sockets.
+ */
+class Socket {
+private:
+  // Buffer size, chosen to fit in a single packet after TCP/IP overhead.
+  static const int BUF_SIZE = 1400;
+  
+  // Can't rely on a sentinel value for the socket descriptor
+  bool connected;
+  
+  SOCKETTYPE sock;
+  
+  // Read buffer
+  char* readBuf;
+  
+  // One bye past end of valid data in readBuf
+  char* readValid;
+  
+  // Current read pointer
+  char* readBufPtr;
+
+  // Write buffer
+  char* writeBuf;
+  
+  // Current write pointer
+  char* writeBufPtr;
+
+  // Stats
+  unsigned long numReads;
+  unsigned long long totReadBytes;
+  size_t maxReadBytes;
+
+  unsigned long numWrites;
+  unsigned long long totWriteBytes;
+  size_t maxWriteBytes;
+
+private:
+  void init();
+  bool fillReadBuf();
+  bool emptyWriteBuf();
+
+public:
+  Socket() : connected(false), readBuf(new char[BUF_SIZE]), writeBuf(new char[BUF_SIZE]) {
+    readBufPtr = readValid = readBuf;
+    writeBufPtr = writeBuf;
+    numReads = numWrites = 0;
+    maxReadBytes = maxWriteBytes = 0;
+    totReadBytes = totWriteBytes = 0;
+    init();
+  }
+  
+  ~Socket() {
+    disconnect();
+#ifdef _WINDOWS
+    if (0) WSACleanup();
+#endif
+    // TODO(jat): LEAK LEAK LEAK
+    // delete[] readBuf;
+    // delete[] writeBuf;
+    Debug::log(Debug::Debugging) << "Socket: #r=" << numReads << ", bytes/read="
+        << (numReads ? totReadBytes / numReads : 0) << ", maxr=" << maxReadBytes << "; #w="
+        << numWrites << ", bytes/write=" << (numWrites ? totWriteBytes / numWrites : 0) << ", maxw="
+        << maxWriteBytes << Debug::flush;
+  }
+
+  /**
+   * Connects this socket to a specified port on a host.
+   * 
+   * @param host host name or IP address to connect to
+   * @param port TCP port to connect to
+   * @return true if the connection succeeds
+   */ 
+  bool connect(const char* host, int port);
+  
+  /**
+   * Returns true if the socket is connected.
+   */
+  bool isConnected() const {
+    return connected;
+  }
+  
+  /**
+   * Disconnect this socket.
+   * 
+   * @param doFlush true (the default value) if the socket should be flushed.
+   * @return true if disconnect succeeds
+   */
+  bool disconnect(bool doFlush = true);
+  
+  /**
+   * Read a single byte from the socket.
+   *
+   * @return -1 on error, otherwise unsigned byte read.
+   */
+  int readByte() {
+    if (readBufPtr >= readValid) {
+      if (!fillReadBuf()) {
+        return -1;
+      }
+    }
+    return static_cast<unsigned char>(*readBufPtr++);
+  }
+  
+  /**
+   * Write a single byte to the socket.
+   * 
+   * @return true on success.
+   */
+  bool writeByte(char c) {
+    if (writeBufPtr >= writeBuf + BUF_SIZE) {
+      if (!emptyWriteBuf()) {
+        return false;
+      }
+    }
+    *writeBufPtr++ = c;
+    return true;
+  }
+  
+  /**
+   * Flush any pending writes on the socket.
+   *
+   * @return true on success
+   */
+  bool flush() {
+    if (writeBufPtr > writeBuf) {
+      if (!emptyWriteBuf()) {
+        return false;
+      }
+    }
+    return true;
+  }
+};
+
+#endif