Example of cooperative rendering into one window by two processes
diff --git a/progs/xdemos/ipc.c b/progs/xdemos/ipc.c
new file mode 100644
index 0000000..fa52b09
--- /dev/null
+++ b/progs/xdemos/ipc.c
@@ -0,0 +1,264 @@
+/* Copyright (c) 2003 Tungsten Graphics, Inc.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files ("the
+ * Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:  The above copyright notice, the Tungsten
+ * Graphics splash screen, and this permission notice shall be included
+ * in all copies or substantial portions of the Software.  THE SOFTWARE
+ * IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Simple IPC API
+ * Brian Paul
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "ipc.h"
+
+#if defined(IRIX) || defined(irix)
+typedef int socklen_t;
+#endif
+
+#define NO_DELAY 1
+
+#define DEFAULT_MASTER_PORT 7011
+
+
+/*
+ * Return my hostname in <nameOut>.
+ * Return 1 for success, 0 for error.
+ */
+int
+MyHostName(char *nameOut, int maxNameLength)
+{
+    int k = gethostname(nameOut, maxNameLength);
+    return k==0;
+}
+
+
+/*
+ * Create a socket attached to a port.  Later, we can call AcceptConnection
+ * on the socket returned from this function.
+ * Return the new socket number or -1 if error.
+ */
+int
+CreatePort(int *port)
+{
+    char hostname[1000];
+    struct sockaddr_in servaddr;
+    struct hostent *hp;
+    int so_reuseaddr = 1;
+    int tcp_nodelay = 1;
+    int sock, k;
+
+    /* create socket */
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    assert(sock > 2);
+
+    /* get my host name */
+    k = gethostname(hostname, 1000);
+    assert(k == 0);
+
+    /* get hostent info */
+    hp = gethostbyname(hostname);
+    assert(hp);
+
+    /* initialize the servaddr struct */
+    memset(&servaddr, 0, sizeof(servaddr) );
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons((unsigned short) (*port));
+    memcpy((char *) &servaddr.sin_addr, hp->h_addr,
+	   sizeof(servaddr.sin_addr));
+
+    /* deallocate when we exit */
+    k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+		   (char *) &so_reuseaddr, sizeof(so_reuseaddr));
+    assert(k==0);
+
+    /* send packets immediately */
+#if NO_DELAY
+    k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+		   (char *) &tcp_nodelay, sizeof(tcp_nodelay));
+    assert(k==0);
+#endif
+
+    if (*port == 0)
+        *port = DEFAULT_MASTER_PORT;
+
+    k = 1;
+    while (k && (*port < 65534)) {
+    	/* bind our address to the socket */
+    	servaddr.sin_port = htons((unsigned short) (*port));
+    	k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
+        if (k)
+           *port = *port + 1;
+    }
+
+#if 0
+    printf("###### Real Port: %d\n", *port);
+#endif
+
+    /* listen for connections */
+    k = listen(sock, 100);
+    assert(k == 0);
+
+    return sock;
+}
+
+
+/*
+ * Accept a connection on the named socket.
+ * Return a new socket for the new connection, or -1 if error.
+ */
+int
+AcceptConnection(int socket)
+{
+    struct sockaddr addr;
+    socklen_t addrLen;
+    int newSock;
+
+    addrLen = sizeof(addr);
+    newSock = accept(socket, &addr, &addrLen);
+    if (newSock == 1)
+	return -1;
+    else
+	return newSock;
+}
+
+
+/*
+ * Contact the server running on the given host on the named port.
+ * Return socket number or -1 if error.
+ */
+int
+Connect(const char *hostname, int port)
+{
+    struct sockaddr_in servaddr;
+    struct hostent *hp;
+    int sock, k;
+    int tcp_nodelay = 1;
+
+    assert(port);
+
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    assert(sock >= 0);
+
+    hp = gethostbyname(hostname);
+    assert(hp);
+
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons((unsigned short) port);
+    memcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr));
+
+    k = connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
+    if (k != 0) {
+       perror("Connect:");
+       return -1;
+    }
+
+#if NO_DELAY
+    /* send packets immediately */
+    k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+		   (char *) &tcp_nodelay, sizeof(tcp_nodelay));
+    assert(k==0);
+#endif
+
+    return sock;
+}
+
+
+void
+CloseSocket(int socket)
+{
+    close(socket);
+}
+
+
+int
+SendData(int socket, const void *data, int bytes)
+{
+    int sent = 0;
+    int b;
+
+    while (sent < bytes) {
+        b = write(socket, (char *) data + sent, bytes - sent);
+        if (b <= 0)
+            return -1; /* something broke */
+        sent += b;
+    }
+    return sent;
+}
+
+
+int
+ReceiveData(int socket, void *data, int bytes)
+{
+    int received = 0, b;
+
+    while (received < bytes) {
+        b = read(socket, (char *) data + received, bytes - received);
+        if (b <= 0)
+            return -1;
+        received += b;
+    }
+    return received;
+}
+
+
+int
+SendString(int socket, const char *str)
+{
+    const int len = strlen(str);
+    int sent, b;
+
+    /* first, send a 4-byte length indicator */
+    b = write(socket, &len, sizeof(len));
+    if (b <= 0)
+	return -1;
+
+    sent = SendData(socket, str, len);
+    assert(sent == len);
+    return sent;
+}
+
+
+int
+ReceiveString(int socket, char *str, int maxLen)
+{
+    int len, received, b;
+
+    /* first, read 4 bytes to see how long of string to receive */
+    b = read(socket, &len, sizeof(len));
+    if (b <= 0)
+	return -1;
+
+    assert(len <= maxLen);  /* XXX fix someday */
+    assert(len >= 0);
+    received = ReceiveData(socket, str, len);
+    assert(received != -1);
+    assert(received == len);
+    str[len] = 0;
+    return received;
+}