buffet: Add an XMPP client class

This is a relatively simple XMPP client class, which at this point,
is only used to keep the XMPP connection open to GCD.

TEST=FEATURES=test emerge buffet
BUG=brillo:95

Change-Id: I2e7c8d7352892bd7c94e630cc7872f32f2298ae4
Reviewed-on: https://chromium-review.googlesource.com/248351
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Nathan Bullock <nathanbullock@google.com>
Tested-by: Nathan Bullock <nathanbullock@google.com>
diff --git a/buffet/xmpp/xmpp_connection.cc b/buffet/xmpp/xmpp_connection.cc
new file mode 100644
index 0000000..8799493
--- /dev/null
+++ b/buffet/xmpp/xmpp_connection.cc
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "buffet/xmpp/xmpp_connection.h"
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <base/files/file_util.h>
+#include <chromeos/syslog_logging.h>
+
+namespace buffet {
+
+XmppConnection::~XmppConnection() {
+  if (fd_ > 0) {
+    close(fd_);
+  }
+}
+
+bool XmppConnection::Initialize() {
+  LOG(INFO) << "Opening XMPP connection";
+
+  fd_ = socket(AF_INET, SOCK_STREAM, 0);
+
+  // TODO(nathanbullock): Use gethostbyname_r.
+  struct hostent* server = gethostbyname("talk.google.com");
+  if (server == NULL) {
+    LOG(WARNING) << "Failed to find host talk.google.com";
+    return false;
+  }
+
+  sockaddr_in serv_addr;
+  memset(&serv_addr, 0, sizeof(serv_addr));
+  serv_addr.sin_family = AF_INET;
+  bcopy(server->h_addr, &(serv_addr.sin_addr), server->h_length);
+  serv_addr.sin_port = htons(5222);
+
+  if (connect(fd_, (struct sockaddr*)&serv_addr, sizeof(sockaddr)) < 0) {
+    LOG(WARNING) << "Failed to connect to talk.google.com:5222";
+    return false;
+  }
+
+  return true;
+}
+
+bool XmppConnection::Read(std::string* msg) const {
+  char buffer[4096];  // This should be large enough for our purposes.
+  ssize_t bytes = HANDLE_EINTR(read(fd_, buffer, sizeof(buffer)));
+  if (bytes < 0) {
+    LOG(WARNING) << "Failure reading";
+    return false;
+  }
+  *msg = std::string{buffer, static_cast<size_t>(bytes)};
+  VLOG(1) << "READ: (" << msg->size() << ")" << *msg;
+  return true;
+}
+
+bool XmppConnection::Write(const std::string& msg) const {
+  VLOG(1) << "WRITE: (" << msg.size() << ")" << msg;
+  if (!base::WriteFileDescriptor(fd_, msg.c_str(), msg.size())) {
+    LOG(WARNING) << "Failure writing";
+    return false;
+  }
+  return true;
+}
+
+}  // namespace buffet