From 4fc97523c78f723c2d4eb01e2d3b6dd4ee695138 Mon Sep 17 00:00:00 2001
From: Damien Lefortier <damien.lefortier@gmail.com>
Date: Mon, 21 Mar 2011 22:50:17 +0100
Subject: [PATCH] Create a simple C connector in connector/c.

---
 CMakeLists.txt             |  1 +
 connector/CMakeLists.txt   |  1 +
 connector/c/CMakeLists.txt |  1 +
 connector/c/client.c       | 85 ++++++++++++++++++++++++++++++++++++++
 connector/c/client.h       | 69 +++++++++++++++++++++++++++++++
 5 files changed, 157 insertions(+)
 create mode 100644 connector/CMakeLists.txt
 create mode 100644 connector/c/CMakeLists.txt
 create mode 100644 connector/c/client.c
 create mode 100644 connector/c/client.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c757d3b553..83186d7f50 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -172,6 +172,7 @@ endif()
 
 add_subdirectory(third_party)
 add_subdirectory(cfg)
+add_subdirectory(connector)
 add_subdirectory(core)
 add_subdirectory(mod)
 add_subdirectory(test)
diff --git a/connector/CMakeLists.txt b/connector/CMakeLists.txt
new file mode 100644
index 0000000000..20bc4cc4b0
--- /dev/null
+++ b/connector/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(c)
diff --git a/connector/c/CMakeLists.txt b/connector/c/CMakeLists.txt
new file mode 100644
index 0000000000..d7e8123b28
--- /dev/null
+++ b/connector/c/CMakeLists.txt
@@ -0,0 +1 @@
+add_library(client client.c)
diff --git a/connector/c/client.c b/connector/c/client.c
new file mode 100644
index 0000000000..4597f2feee
--- /dev/null
+++ b/connector/c/client.c
@@ -0,0 +1,85 @@
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <connector/c/client.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+static
+struct sockaddr_in
+get_sockaddr_in(const char *hostname, unsigned short port) {
+  struct sockaddr_in result;
+
+  memset((void*)(&result), 0, sizeof(result));
+  result.sin_family = AF_INET;
+  result.sin_port   = htons(port);
+
+  struct hostent *host = gethostbyname(hostname);
+  if (host != 0)
+	  memcpy((void*)(&result.sin_addr),
+		 (void*)(host->h_addr), host->h_length);
+
+  return result;
+}
+
+struct tnt_connection *tnt_connect(const char *hostname, int port) {
+  int fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (fd < 0)
+	  return NULL;
+
+  int opt = 1;
+  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) == -1)
+	  return NULL;
+
+  struct sockaddr_in addr = get_sockaddr_in(hostname, port);
+  if (connect(fd, (struct sockaddr*)&addr, sizeof addr))
+	  return NULL;
+
+  struct tnt_connection *conn = malloc(sizeof(struct tnt_connection));
+  conn->data_port = fd;
+  return conn;
+}
+
+void tnt_disconnect(struct tnt_connection *conn) {
+  close(conn->data_port);
+  free(conn);
+}
+
+int tnt_execute_raw(struct tnt_connection *conn, const char *message,
+		    size_t len) {
+  if (send(conn->data_port, message, len, 0) < 0)
+	  return 3;
+
+  char buf[2048];
+  if (recv(conn->data_port, buf, 2048, 0) < 16)
+	  return 3;
+
+  return buf[12]; // return_code: 0,1,2
+}
diff --git a/connector/c/client.h b/connector/c/client.h
new file mode 100644
index 0000000000..034ba5cc00
--- /dev/null
+++ b/connector/c/client.h
@@ -0,0 +1,69 @@
+#ifndef TARANTOOL_CONNECTOR_CLIENT_H_INCLUDED
+# define TARANTOOL_CONNECTOR_CLIENT_H_INCLUDED
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * C client library for tarantool.
+ */
+
+#include <stddef.h>
+
+/**
+ * A connection with a Tarantool server.
+ */
+struct tnt_connection {
+	int data_port;
+};
+
+/**
+ * Open a connection with a Tarantool server.
+ *
+ * @param hostname the hostname of the server.
+ * @param port the port of the server.
+ *
+ * @return a newly opened connection or NULL if there was an error.
+ */
+struct tnt_connection *tnt_connect(const char *hostname, int port);
+
+/**
+ * Close a connection.
+ *
+ * @param conn the connection.
+ */
+void tnt_disconnect(struct tnt_connection *conn);
+
+/**
+ * Execute a statement on a connection
+ *
+ * @param conn the connection.
+ * @param message a raw message following Tarantool protocol.
+ * @param len the length of the message.
+ *
+ * @return the status code: 0,1,2 if the statement was successufully
+ * sent (see Tarantool protocol) or 3 if an error occured.
+ */
+int tnt_execute_raw(struct tnt_connection *conn, const char *message,
+		    size_t len);
+
+#endif /* TARANTOOL_CONNECTOR_CLIENT_H_INCLUDED */
-- 
GitLab