aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/c_src/esock_osio.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/c_src/esock_osio.c')
-rw-r--r--lib/ssl/c_src/esock_osio.c328
1 files changed, 328 insertions, 0 deletions
diff --git a/lib/ssl/c_src/esock_osio.c b/lib/ssl/c_src/esock_osio.c
new file mode 100644
index 0000000000..41c5271c16
--- /dev/null
+++ b/lib/ssl/c_src/esock_osio.c
@@ -0,0 +1,328 @@
+/*<copyright>
+ * <year>1999-2008</year>
+ * <holder>Ericsson AB, All Rights Reserved</holder>
+ *</copyright>
+ *<legalnotice>
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Initial Developer of the Original Code is Ericsson AB.
+ *</legalnotice>
+ */
+/*
+ * Purpose: Std filedescriptors, break handler
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef __WIN32__
+#include "esock_winsock.h"
+#include <process.h>
+#include <io.h>
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#include <signal.h>
+#endif
+
+#include "esock.h"
+#include "debuglog.h"
+#include "esock_utils.h"
+#include "esock_osio.h"
+
+#ifdef __WIN32__
+#define write _write
+#define read _read
+#define LOCALHOSTADDR "127.0.0.1"
+#define LOCBUFSIZE 1024
+#endif
+
+#define PACKET_SIZE 4
+#define EBUFSIZE 256
+
+FD local_read_fd = 0;
+
+static int inc_rbuf(int size);
+static void free_rbuf(void);
+static int read_fill(unsigned char *buf, int len);
+#ifdef __WIN32__
+static int create_local_thread(void);
+static DWORD WINAPI local_thread(LPVOID lpvParam);
+static BOOL WINAPI signal_handler(DWORD ctrl);
+#endif
+
+static unsigned char *rbuf = NULL;
+static int rbuf_malloced = 0;
+#ifdef __WIN32__
+static unsigned long one = 1, zero = 0;
+static int local_portno;
+static char *local_buf;
+#endif
+
+int set_break_handler(void)
+{
+#ifndef __WIN32__
+ struct sigaction act;
+
+ /* Ignore SIGPIPE signal */
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ return 0;
+#else
+ SetConsoleCtrlHandler(signal_handler, TRUE);
+ return 0;
+#endif
+}
+
+
+#ifdef __WIN32__
+
+int set_binary_mode(void)
+{
+ _setmode(0, _O_BINARY);
+ _setmode(1, _O_BINARY);
+ return 0;
+}
+
+int esock_osio_init(void)
+{
+ return create_local_thread();
+}
+
+void esock_osio_finish(void)
+{
+ sock_close(local_read_fd);
+}
+
+#endif
+
+int read_ctrl(unsigned char **ebufp)
+{
+ int tbh, cc;
+ unsigned char *mbuf;
+
+ if (inc_rbuf(EBUFSIZE) < 0) {
+ fprintf(stderr, "read_ctrl: cannot alloc rbuf\n");
+ return -1;
+ }
+ cc = read_fill(rbuf, PACKET_SIZE);
+ if (cc < 0) {
+ free_rbuf();
+ return -1;
+ }
+ if (cc == 0) {
+ free_rbuf();
+ return -1; /* XXX 0 ?? */
+ }
+ tbh = GET_INT32(rbuf);
+
+ if (tbh > rbuf_malloced - 4) {
+ if (inc_rbuf(tbh + 4) < 0)
+ return -1;
+ }
+
+ mbuf = rbuf + PACKET_SIZE;
+ cc = read_fill(mbuf, tbh);
+ DEBUGF(("-----------------------------------\n"));
+ DEBUGF(("read_ctrl: cc = %d\n", cc));
+ if(cc > 0) {
+ DEBUGMSGF(("message (hex) : [%3.*a]\n", cc, mbuf));
+ DEBUGMSGF(("message (char): [%3.*b]\n", cc, mbuf));
+ }
+ *ebufp = mbuf;
+ return cc;
+}
+
+int write_ctrl(unsigned char *buf, int len)
+{
+ unsigned char lb[4];
+
+ PUT_INT32(len, lb);
+ DEBUGF(("write_ctrl: len = %d\n", len));
+ DEBUGMSGF(("message (hex) : [%3.*a] [%3.*a]\n", PACKET_SIZE, lb,
+ len, buf));
+ DEBUGMSGF(("message (char): [%3.*b] [%3.*b]\n", PACKET_SIZE, lb,
+ len, buf));
+
+ if (write(1, lb, PACKET_SIZE) != PACKET_SIZE) { /* XXX */
+ fprintf(stderr, "write_ctrl: Bad write \n");
+ return -1;
+ }
+ if (write(1, buf, len) != len) { /* XXX */
+ fprintf(stderr, "write_ctrl: Bad write \n");
+ return -1;
+ }
+ return len;
+}
+
+
+/*
+ * Local functions
+ *
+ */
+
+static int inc_rbuf(int size)
+{
+ unsigned char *nbuf;
+
+ if (rbuf_malloced >= size)
+ return 0;
+ if (rbuf != NULL)
+ nbuf = esock_realloc(rbuf, size);
+ else
+ nbuf = esock_malloc(size);
+ if(nbuf != NULL) {
+ rbuf = nbuf;
+ rbuf_malloced = size;
+ return 0;
+ }
+ return -1;
+}
+
+static void free_rbuf(void)
+{
+ if (rbuf != NULL) {
+ esock_free(rbuf);
+ rbuf = NULL;
+ rbuf_malloced = 0;
+ }
+}
+
+/* Fill buffer, return buffer length, 0 for EOF, < 0 for error. */
+
+static int read_fill(unsigned char *buf, int len)
+{
+ int i, got = 0;
+
+ do {
+ if ((i = sock_read(local_read_fd, buf+got, len-got)) <= 0)
+ return i;
+ got += i;
+ } while (got < len);
+ return len;
+}
+
+
+#ifdef __WIN32__
+
+/*
+ * This routine creates a local thread, which reads from standard input
+ * and writes to a socket.
+ */
+
+static int create_local_thread(void)
+{
+ struct sockaddr_in iserv_addr;
+ SOCKET tmpsock;
+ int length;
+ unsigned threadaddr;
+
+ local_buf = esock_malloc(LOCBUFSIZE);
+ if ((tmpsock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
+ fprintf(stderr, "create_local_thread could not create socket.\n");
+ return -1;
+ }
+ memset(&iserv_addr, 0, sizeof(iserv_addr));
+ iserv_addr.sin_family = AF_INET;
+ iserv_addr.sin_addr.s_addr = inet_addr(LOCALHOSTADDR);
+ iserv_addr.sin_port = htons(0); /* Have any port */
+
+ if (bind(tmpsock, (struct sockaddr *) &iserv_addr,
+ sizeof(iserv_addr)) < 0) {
+ fprintf(stderr, "create_local_thread could not bind.\n");
+ closesocket(tmpsock);
+ return -1;
+ }
+ listen(tmpsock, 1);
+ length = sizeof(iserv_addr);
+ if (getsockname(tmpsock, (struct sockaddr *) &iserv_addr, &length) < 0) {
+ fprintf(stderr, "create_local_thread could not getsockname.\n");
+ closesocket(tmpsock);
+ return -1;
+ }
+ local_portno = ntohs(iserv_addr.sin_port);
+
+ if (_beginthreadex(NULL, 0, local_thread, NULL, 0, &threadaddr) == 0) {
+ fprintf(stderr, "create_local_thread could not _beginthreadex().\n");
+ closesocket(tmpsock);
+ return -1;
+ }
+ local_read_fd = accept(tmpsock, (struct sockaddr *) NULL, (int *) NULL);
+ if (local_read_fd == INVALID_FD) {
+ fprintf(stderr, "create_local_thread could not accept.\n");
+ closesocket(tmpsock);
+ return -1;
+ }
+ closesocket(tmpsock);
+ return 0;
+}
+
+static DWORD WINAPI local_thread(LPVOID lpvParam)
+{
+ SOCKET sock;
+ struct hostent *host;
+ char hostname[64];
+ struct sockaddr_in iserv_addr;
+ unsigned long addr;
+ int len;
+ HANDLE thread;
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ memset(&iserv_addr, 0, sizeof(struct sockaddr_in));
+ iserv_addr.sin_family = AF_INET;
+ iserv_addr.sin_addr.s_addr = inet_addr(LOCALHOSTADDR);
+ iserv_addr.sin_port = htons(local_portno);
+ if(connect(sock, (struct sockaddr*)&iserv_addr, sizeof iserv_addr) ==
+ SOCKET_ERROR) {
+ fprintf(stderr, "local_thread thread could not connect\n");
+ closesocket(sock);
+ return 0;
+ }
+ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
+
+ /* read from 0 and write to sock */
+ while (1) {
+ if ((len = read(0, local_buf, LOCBUFSIZE)) <= 0) {
+ closesocket(sock);
+ close(0);
+ return 0;
+ }
+ if (send(sock, local_buf, len, 0) != len ) {
+ closesocket(sock);
+ close(0);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/* Signal handler */
+
+static BOOL WINAPI signal_handler(DWORD ctrl)
+{
+ switch (ctrl) {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ break;
+ case CTRL_LOGOFF_EVENT:
+ if (!getenv("ERLSRV_SERVICE_NAME"))
+ return FALSE;
+ break;
+ default:
+ exit(1);
+ }
+ return TRUE;
+}
+
+#endif