[mw-devel] MW3 r944 - branches/newipc3/src

arthur at sucs.org arthur at sucs.org
Thu Mar 29 20:39:54 BST 2007


Author: arthur
Date: 2007-03-29 20:39:49 +0100 (Thu, 29 Mar 2007)
New Revision: 944

Added:
   branches/newipc3/src/server.c
   branches/newipc3/src/session.c
   branches/newipc3/src/session.h
   branches/newipc3/src/socket.c
   branches/newipc3/src/socket.h
Modified:
   branches/newipc3/src/Makefile
   branches/newipc3/src/main.c
Log:
import the marvin message passing framework, refs #14


Modified: branches/newipc3/src/Makefile
===================================================================
--- branches/newipc3/src/Makefile	2007-03-29 19:34:18 UTC (rev 943)
+++ branches/newipc3/src/Makefile	2007-03-29 19:39:49 UTC (rev 944)
@@ -43,7 +43,7 @@
 
 CFLAGS += $(DEFS)
 
-all: mw red help
+all: mw red help server
 
 CODE=$(wildcard *.c)
 HDRS=$(wildcard *.h)
@@ -81,7 +81,7 @@
 topten.o sort.o tidyup.o gags.o script_inst.o script.o\
 incoming.o command.o chattable.o alias.o frl.o hash.o vars.o expand.o\
 mud.o mudtable.o files.o completion.o sentinel.o iconv.o gagtable.o \
-js.o sqlite.o ipc.o
+js.o sqlite.o ipc.o session.o socket.o
 	$(CC) $(LDFLAGS) $(LDLIBS) -o $@ $^
 
 setup_homepath:
@@ -97,6 +97,8 @@
 red: red.c
 	$(CC) -o $@ $^
 
+server: server.o socket.o session.o
+
 # files to install to $(HOMEPATH) (not including the executable which goes in /usr/bin)
 INSTALLFILES = colour help login.banner mesgs mudhelp rooms scripthelp talkhelp wizhelp users.bb folders.bb who.bb log.bb COPYING INSTALL LICENSE README
 install: mw setup_homepath

Modified: branches/newipc3/src/main.c
===================================================================
--- branches/newipc3/src/main.c	2007-03-29 19:34:18 UTC (rev 943)
+++ branches/newipc3/src/main.c	2007-03-29 19:39:49 UTC (rev 944)
@@ -29,6 +29,8 @@
 #include "mud.h"
 #include "mudtable.h"
 #include "completion.h"
+#include "socket.h"
+#include "session.h"
 
 #include <readline/readline.h>
 #include <readline/history.h>
@@ -62,6 +64,11 @@
 extern Alias force_list;
 extern Alias shutdown_list;
 
+#define max(a,b) a>b?a:b
+/* declare that we arent the server just the client */
+int marvin_server=0;
+struct session *session_list=NULL;
+int debug=0;
 
 #ifdef RELEASE
 	static char version[]="Milliways III - Release "VER_MAJ"."VER_MIN"\n";
@@ -300,6 +307,7 @@
 	int folderuser_num = -1;
 	int folderuser_replyto = -1;
 	int msguser_num = -1;
+	int main_socket = -1;
 
 	init_locale();
 #if 0
@@ -493,6 +501,15 @@
 	create_pipe();
 	open_fifo();	
 
+	/* create server socket. WARNING make it less crude */
+	main_socket = socket_connect("localhost", 4000);
+	if (main_socket < 0) {
+		printf("Error opening socket to main server\n");
+	} else {
+		session_list = session_create(main_socket);
+		session_send(session_list, "CMD", "Hi Honey, I'm Home!", -1);
+	}
+
 	/* display all new messages for given user */
 	if (msguser_num>-1 && god_mode())
 	{
@@ -1122,24 +1139,39 @@
 int idle(int fd, int millis)
 {
 	static int in_idle = 0;
-	fd_set readfds, exceptfds;
+	fd_set readfds, exceptfds, writefds;
 	static struct timeval tmout;
 	int nfds;
 	static int fl=0;
 	int select_error;
+	int maxfd = 0;
 
 	in_idle++;
 
 	FD_ZERO(&readfds);
+	FD_ZERO(&writefds);
 	FD_ZERO(&exceptfds);
+
 	FD_SET(incoming_pipe, &readfds);
 	FD_SET(incoming_pipe, &exceptfds);
+	maxfd = max(maxfd, incoming_pipe);
+
+	if (session_list != NULL) {
+		int sock = session_list->socket;
+		FD_SET(sock, &readfds);
+		FD_SET(sock, &exceptfds);
+		maxfd = max(maxfd, sock);
+		if (session_list->tx_queue != NULL)
+			FD_SET(sock, &writefds);
+	}
+
 	if (fd >= 0)
 	{
 		FD_SET(fd, &readfds);
 		FD_SET(fd, &exceptfds);
 		fl = fcntl(fd, F_GETFL);
 		fcntl(fd, F_SETFL, fl & ~O_NDELAY);
+		maxfd = max(maxfd,fd);
 	}
 
 	if (millis >= 0)
@@ -1148,10 +1180,30 @@
 		tmout.tv_usec = (millis % 1000) * 1000;
 	}
 
-	nfds = alarm_select((fd>incoming_pipe)?(fd+1):(incoming_pipe+1), &readfds, NULL, &exceptfds, (millis<0)?(NULL):(&tmout));
+	nfds = alarm_select(maxfd+1, &readfds, &writefds, &exceptfds, (millis<0)?(NULL):(&tmout));
 	select_error = errno;
 	if (fd >= 0) fcntl(fd, F_SETFL, fl);
 	if (nfds > 0) {
+		if (session_list != NULL) {
+			int sock = session_list->socket;
+			if (FD_ISSET(sock, &exceptfds)) {
+				session_drop(session_list);
+				session_list=NULL;
+			} else {
+				if (FD_ISSET(sock, &writefds)) {
+					if (session_write(session_list)) {
+						session_drop(session_list);
+						session_list=NULL;
+					}
+				}
+				if (FD_ISSET(sock, &readfds)) {
+					if (session_read(session_list)) {
+						session_drop(session_list);
+						session_list=NULL;
+					}
+				}
+			}
+		}
 		if (FD_ISSET(incoming_pipe, &exceptfds)) {
 			fprintf(stderr, _("\nError reading incoming message pipe. panic.\n"));
 			return -1;

Added: branches/newipc3/src/server.c
===================================================================
--- branches/newipc3/src/server.c	                        (rev 0)
+++ branches/newipc3/src/server.c	2007-03-29 19:39:49 UTC (rev 944)
@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "socket.h"
+#include "session.h"
+
+int debug=0;
+
+int marvin_server = 1;
+
+/* Root of linked list of connected clients */
+struct session *session_list=NULL;
+
+void main_loop(int main_socket)
+{
+	/* session list iterator */
+	struct session *ptr, *old;
+	/* file descriptor sets for select() */
+	fd_set fd_read, fd_err, fd_write;
+	/* return value from select() */
+	int result;
+	/* time struct passed to select() to specify timeout */
+	struct timeval tt;
+
+	while (1) {
+		/* clear fd sets */
+		FD_ZERO( &fd_read );
+		FD_ZERO( &fd_write );
+		FD_ZERO( &fd_err );
+		
+		/* check for new sessions */
+		FD_SET( main_socket, &fd_read );
+		FD_SET( main_socket, &fd_err );
+
+		/* check socket for each connected client */
+		for (ptr=session_list; ptr!=NULL; ptr=ptr->next) {
+			FD_SET( ptr->socket, &fd_read );
+			FD_SET( ptr->socket, &fd_err );
+			if (ptr->tx_queue != NULL)
+				FD_SET( ptr->socket, &fd_write );
+		}
+
+		/* set timeout */
+		tt.tv_sec = 10;
+		tt.tv_usec = 0;
+
+		/* wait for one or more sockets to become available */
+		result = select(FD_SETSIZE, &fd_read, &fd_write, &fd_err, &tt);
+			
+		if (result < 0) { 
+			fprintf(stderr, "Error on Select : %s\n", strerror(errno));
+			exit(-1);
+		}
+
+		if (result > 0) {
+			/* Accept new incoming session */
+			if (FD_ISSET( main_socket, &fd_read )) {
+				socklen_t len;
+				struct sockaddr_in6 addr;
+				char addr_buff[128];
+				len=sizeof(addr);
+
+				ptr = session_create( accept(main_socket, (struct sockaddr *)&addr, &len) );
+				ptr->next=session_list;
+				session_list=ptr;
+				printf("Accepted connection %d from [%s]:%d\n",
+					ptr->socket, inet_ntop(addr.sin6_family,&(addr.sin6_addr),addr_buff,128), ntohs(addr.sin6_port) );
+			
+			}
+
+			/* Master socket had an error, this is bad */
+			if (FD_ISSET( main_socket, &fd_err)) {
+				fprintf(stderr, "Error on main socket.\n");
+			}
+
+			/* check other sockets for activity */	
+			ptr = session_list;
+			while (ptr!=NULL) {
+				/* error on socket, close it */
+				if (FD_ISSET( ptr->socket, &fd_err )) {
+					fprintf(stderr, "Error on socket %d, dropping.\n", ptr->socket);
+					old=ptr;
+					ptr=ptr->next;
+					session_drop(old);
+				} else {
+					/* socket ready for reading */
+					if (FD_ISSET( ptr->socket, &fd_read )) {
+						if (debug) printf("Read event on %d\n", ptr->socket);
+						fflush(stdout);
+						if (session_read(ptr)) {
+							old = ptr;
+							ptr=ptr->next;
+							session_drop(old);
+							printf("session dropped during session_read\n");
+							continue;
+						}
+					}
+					/* socket ready for writing */
+					if (ptr->tx_queue!=NULL && FD_ISSET( ptr->socket, &fd_write )) {
+						if (debug) printf("Write event on %d\n", ptr->socket);
+						if (session_write(ptr)) {
+							old = ptr;
+							ptr=ptr->next;
+							session_drop(old);
+							printf("session dropped during session_write\n");
+							continue;
+						}
+					}
+					ptr=ptr->next;
+				}
+			}
+		}
+		if (result == 0) {
+			if (debug) {
+	//			printf("Timeout.\n");
+				ptr=session_list;
+				for (ptr=session_list; ptr!=NULL; ptr=ptr->next) {
+					session_debug(ptr);
+				}
+			}
+		}
+	}
+}
+
+/* these are dummies in the server as we dont use readline */
+void enable_rl(void) {}
+void disable_rl(int i) {}
+
+int main(int argc, char **argv)
+{
+	int main_socket;
+	unsigned short port;
+	struct sockaddr_in6 addr;
+	socklen_t size=sizeof(addr);
+	char addr_buff[128];
+
+	if (argc>1) {
+		port=atoi(argv[1]);
+	} else
+		port=DEFAULT_PORT;
+
+	main_socket=socket_listen(port);
+
+	if (main_socket < 0) {
+		printf("Failed to open the master server port.\n");
+		exit(0);
+	}
+
+	getsockname(main_socket, (struct sockaddr *)&addr, &size);
+	printf("Server started on %s port %d\n", inet_ntop(addr.sin6_family,&(addr.sin6_addr),addr_buff,128), ntohs(addr.sin6_port) );
+	main_loop(main_socket);
+	
+	return 0;
+}

Added: branches/newipc3/src/session.c
===================================================================
--- branches/newipc3/src/session.c	                        (rev 0)
+++ branches/newipc3/src/session.c	2007-03-29 19:39:49 UTC (rev 944)
@@ -0,0 +1,396 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "socket.h"
+#include "session.h"
+
+extern int marvin_server;
+extern int debug;
+
+void enable_rl(void);
+void disable_rl(int);
+
+/* Prototype for external message catcher */
+void session_recv( struct session * );
+
+rxstate text2state( char *t )
+{
+	if (strcasecmp(t, "CMD")==0)
+		return CMD;
+	else
+	if (strcasecmp(t, "RPY")==0)
+		return RPY;
+	else
+	if (strcasecmp(t, "ERR")==0)
+		return ERR;
+	else
+		return NONE;
+}
+
+/* print debugging info about socket */
+void session_debug(struct session *ptr)
+{
+	printf("sock %d. size=%d expect=%d limit=%d", ptr->socket, ptr->recv_size, ptr->expect, ptr->recv_limit);
+	if (ptr->recv_size > 0) {
+		ptr->recv_buff[ptr->recv_size]=0;
+		printf(": '%s'", ptr->recv_buff);
+	}
+	printf("\n");
+}
+
+/* create a new session structure */
+struct session * session_create( int sock )
+{
+	struct session *ptr;
+	ptr=(struct session *)malloc(sizeof(struct session));
+	ptr->expect=0;
+	ptr->recv_size=0;
+	ptr->recv_limit=0;
+	ptr->recv_buff=NULL;
+	ptr->tx_queue=NULL;
+	ptr->next = NULL;
+	ptr->socket = sock;
+
+	return ptr;
+}
+
+/* write waiting data down socket */
+int session_write( struct session *sess )
+{
+	int j,k;
+	struct txq *send;
+
+	if (sess->tx_queue == NULL) {
+		if (debug) printf("Write request on empty queue.\n");
+		return 0;
+	}
+
+	send = sess->tx_queue;
+
+	/* That was the last message, ever, so shut up shop */
+	if (send->final) {
+		return 1;
+	}
+
+	/* do we need to send an intro first */
+	if (send->intro != NULL) {
+		if (write(sess->socket, send->intro, strlen(send->intro))<0) {
+			return 1;
+		}
+		if (debug) printf("Sent %ld intro bytes.\n", strlen(send->intro));
+		free(send->intro);
+		send->intro = NULL;
+		return 0;
+	}
+
+	/* how much left to send */
+	j = send->limit - send->size;
+	/* dont send too much, less than MTU */
+	if (j>256) j = 256;
+
+	k=write(sess->socket, send->body, j);
+	if (k<0) {
+	       return 1;
+	}
+	send->size += k;
+	if (debug) printf("Sent %d body bytes.\n", k);
+
+	/* This item done, bring up the next */
+	if (send->size >= send->limit) {
+		free(send->body);
+		send->body = NULL;
+		send->limit = 0;
+		send->size = 0;
+		sess->tx_queue = send->next;
+		free(send);
+	}
+	return 0;
+}
+
+/* Public function. Queue item for sending */
+void session_send(struct session *s, const char *cmd, const char *body, int len)
+{
+	struct txq *new, *ptr;
+	if (len < 0) len = strlen(body);
+
+	new = malloc( sizeof(struct txq) );
+	new->size = 0;
+	new->limit = len;
+	new->intro = malloc(80);
+	new->body = malloc(len);
+	new->next = NULL;
+	new->final = 0;
+
+	snprintf(new->intro, 80, "%s %d\r\n", cmd, len);
+	memcpy(new->body, body, len);
+
+	/* if we are the client, there is only one session */
+	if (!marvin_server) s = session_list;
+
+	/* find the end and attach the new item */
+	ptr = s->tx_queue;
+	while (ptr != NULL && ptr->next != NULL)
+		ptr=ptr->next;
+	if (s->tx_queue == NULL)
+		s->tx_queue = new;
+	else
+		ptr->next = new;
+	if (debug) printf("Queue new outgoing message.\n");
+}
+
+/* request the closing of the session */
+void session_end(struct session *s)
+{
+	struct txq *new, *ptr;
+
+	new = malloc( sizeof(struct txq) );
+	new->size = 0;
+	new->limit = 0;
+	new->intro = NULL;
+	new->body = NULL;
+	new->next = NULL;
+	new->final = 1;
+
+	/* if we are the client, there is only one session */
+	if (!marvin_server) s = session_list;
+
+	/* find the end and attach the new item */
+	ptr = s->tx_queue;
+	while (ptr != NULL && ptr->next != NULL)
+		ptr=ptr->next;
+	if (s->tx_queue == NULL)
+		s->tx_queue = new;
+	else
+		ptr->next = new;
+	if (debug) printf("Queued session terminate message.\n");
+}
+
+/* read waiting data from socket */
+int session_read( struct session *s )
+{
+	/* This session has data ready */
+	int i,n;
+
+	if (s->expect > 0 ) {
+		if (debug) {
+			printf("read body: ");
+			session_debug(s);
+		}
+
+		/* we are expecting a body, read what we want */
+		i = s->expect - s->recv_size;
+		n = read(s->socket, &s->recv_buff[s->recv_size], i);
+
+		/* read went bad, ditch connection */
+		if ( n < 0 ) {
+			return 1;
+		}
+
+		s->recv_size += n;
+	
+		/* got entire body, process it */
+		if (s->recv_size >= s->expect) {
+			session_recv(s);
+			/* we had too much, preserve the excess */
+			if (s->recv_size > s->expect) {
+				n = s->recv_size - s->expect;
+				memmove(s->recv_buff, &s->recv_buff[s->expect], n);
+				s->recv_size = n;
+			} else
+				s->recv_size = 0;
+			s->expect = 0;
+		}
+	} else {
+		/* we expect a command line string */
+		char *ptr;
+
+		if (debug) {
+			printf("read cmd: ");
+			session_debug(s);
+		}
+
+		/* grab some more text */
+		if ( s->recv_size + 32 >= s->recv_limit) {
+			s->recv_limit += 256;
+			s->recv_buff = realloc(s->recv_buff, s->recv_limit);
+		}
+		n = read(s->socket, &s->recv_buff[s->recv_size], 31);
+		if ( n < 0 ) {
+			fprintf(stderr, "read error");
+			return 1;
+		}
+
+		if ( n == 0 ) {
+			fprintf(stderr, "EOF, say bye bye\n");
+			return 1;
+		}
+
+		s->recv_size += n;
+		s->recv_buff[s->recv_size]=0;
+		/* does the text contain a new line yet ? */
+		if ((ptr = strchr(s->recv_buff, '\n')) != NULL) {
+			char *cmd;
+			/* copy the line upto \n */
+			*ptr = 0;
+			ptr++;
+			n = s->recv_size - (ptr - s->recv_buff);
+			cmd = strdup(s->recv_buff);
+			/* shuffle the result back down */
+			memmove(s->recv_buff, ptr, n);
+			s->recv_size = n;
+	
+			/* now process the string */
+			return session_command(s, cmd);
+		}
+	}
+	return 0;
+}
+
+/* close and free a session */
+void session_drop( struct session *old )
+{
+	struct session *prev;
+	int sock;
+
+	prev=session_list;
+	while (prev!=NULL && prev != old && prev->next != old)
+		prev=prev->next;
+
+	if (prev == NULL) {
+		fprintf(stderr,"Tried to close a non-existant session.\n");
+		return;
+	}
+
+	if (old == session_list) {
+		session_list=old->next;
+	} else {
+		prev->next=old->next;
+	}
+
+	sock = old->socket;
+	close(old->socket);
+	old->socket = -1;
+	/* clear out all the malloced space */
+	if (old->recv_buff != NULL) free(old->recv_buff);
+	old->recv_buff = 0;
+	if (old->tx_queue != NULL) {
+		struct txq *next, *oldtx;
+		next = old->tx_queue;
+		while (next != NULL) {
+			if (next->intro != NULL) free(next->intro);
+			if (next->body != NULL) free(next->body);
+			oldtx = next->next;
+			free(next);
+			next=oldtx;
+		}
+	}
+	old->tx_queue = NULL;
+	free(old);
+	/* Tell the interpreter what just happened
+	if (marvin_server)
+		slang_exec("session_gone", "i", sock);
+	else
+		slang_exec("shutdown", "");
+	*/
+}
+
+/* process a command string */
+int session_command( struct session *s, char *command)
+{
+	char *cmd, *ptr;
+
+	cmd = strtok(command, " \t\n\r");
+	ptr = strtok(NULL, "\n\r");
+
+
+	if (cmd == NULL) {
+		/* Empty command line */
+		return 0;
+	}
+
+	if (strcasecmp(cmd, "QUIT")==0) {
+		session_send(s, "RPY", "Bye then...", -1);
+		return 1;
+	} else 
+	if (strcasecmp(cmd, "SHUTDOWN")==0) {
+		exit(0);
+	} else
+	if (strcasecmp(cmd, "CMD")==0 
+	||  strcasecmp(cmd, "RPY")==0 
+        ||  strcasecmp(cmd, "ERR")==0) {
+		int n;
+		char *end;
+
+		n= strtol(ptr,&end,10);
+		if (end!=ptr) {
+			s->expect = n;
+			if (s->recv_limit < n) {
+				s->recv_limit = n+32;
+				s->recv_buff = realloc(s->recv_buff, s->recv_limit);
+			}
+			//printf("Recv %s for %d bytes.\n", cmd, n);
+			s->recv_state = text2state( cmd );
+			if (s->expect == 0)
+				session_recv(s);
+			else
+			if (s->recv_size >= s->expect)
+				session_read(s);
+		} else {
+			session_send(s, "ERR", "Incomplete command", -1);
+		}
+	} else {
+		session_send(s, "ERR", "What in feck was that ?", -1);
+		printf("Received command '%s' '%s'\n", cmd, ptr);
+	}
+	free(command);
+	return 0;
+}
+
+struct session * session_find( int sock )
+{
+	struct session *ptr;
+	ptr = session_list;
+	while (ptr != NULL) {
+		if (ptr->socket == sock)
+			break;
+		ptr=ptr->next;
+	}
+	return ptr;
+}
+
+/* Catch incoming messages */
+void session_recv( struct session *s )
+{
+	char *data;
+
+	/* parse the message into an xml tree */
+	data = malloc(s->recv_size+1);
+	memcpy(data, s->recv_buff, s->recv_size);
+	data[s->recv_size]=0;
+
+
+	switch (s->recv_state) {
+	case CMD:
+		printf("CMD sess=%d '%s'\n", s->socket, data);
+		break;
+	case RPY:
+		printf("RPY sess=%d '%s'\n", s->socket, data);
+		break;
+	case ERR:
+		printf("ERR sess=%d '%s'\n", s->socket, data);
+		break;
+	default:
+		printf("??? sess=%d '%s'\n", s->socket, data);
+		break;
+	}
+	
+	free(data); 
+}

Added: branches/newipc3/src/session.h
===================================================================
--- branches/newipc3/src/session.h	                        (rev 0)
+++ branches/newipc3/src/session.h	2007-03-29 19:39:49 UTC (rev 944)
@@ -0,0 +1,38 @@
+struct txq {
+	int final;			/* Close the connection after this */
+	int size;			/* bytes sent 			*/
+	int limit;			/* Size of buffer		*/
+	char *intro;			/* message header 		*/
+	char *body;			/* message body 		*/
+	struct txq *next;
+};
+
+typedef enum { NONE, CMD, RPY, ERR } rxstate;
+
+struct session {
+	int socket;			/* the socket fd */
+
+	rxstate recv_state;		/* recv state */
+	int recv_size;			/* how much data in recv buff */
+	int expect;			/* how much do we expect to recv */
+	int recv_limit;			/* how much space total in recv	*/
+	char *recv_buff;		/* recv storage buffer	 */
+
+	struct txq *tx_queue;	/* outgoing message queue */
+
+	struct session *next;
+};
+
+extern struct session *session_list;
+
+/* Prototypes */
+void session_debug(struct session *ptr);
+struct session *session_create(int sock);
+int session_write(struct session *sess);
+void session_send(struct session *s, const char *cmd, const char *body, int len);
+int session_read(struct session *s);
+void session_drop(struct session *old);
+int session_command(struct session *s, char *command);
+struct session * session_find( int sock );
+void session_end(struct session *sess);
+

Added: branches/newipc3/src/socket.c
===================================================================
--- branches/newipc3/src/socket.c	                        (rev 0)
+++ branches/newipc3/src/socket.c	2007-03-29 19:39:49 UTC (rev 944)
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netdb.h>
+#include <string.h>
+
+union addr {
+	struct sockaddr		generic;
+	struct sockaddr_in	ipv4;
+	struct sockaddr_in6	ipv6;
+};
+
+
+/*
+ *	Create the server socket
+ */
+ 
+int socket_listen(unsigned short port)
+{
+	int v;
+	static struct sockaddr_in6 myaddress;
+	int tos = IPTOS_LOWDELAY;
+	int reuse = 1;
+
+	myaddress.sin6_family=AF_INET6;
+	myaddress.sin6_addr = in6addr_any;
+	myaddress.sin6_port=htons(port);
+
+	v=socket(myaddress.sin6_family,SOCK_STREAM,IPPROTO_TCP);
+	if(v==-1)
+	{
+		fprintf(stderr,"Error on INET socket: %s\n",strerror(errno));
+		return(-1);
+	}
+	setsockopt(v,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));
+	setsockopt(v,SOL_IP,IP_TOS,&tos,sizeof(tos));
+
+	while(bind(v,(struct sockaddr *)&myaddress,sizeof(myaddress))<0)
+	{
+		if(errno != EADDRINUSE)
+		{
+			close(v);
+			fprintf(stderr,"Error on INET bind: %s\n",
+				strerror(errno));
+			return(-1);
+		}
+		printf("Address in use: Retrying...\n");
+		sleep(5);
+	}
+	if(listen(v,1))
+	{
+		fprintf(stderr,"Error on INET listen : %s\n",strerror(errno));
+		return(-1);
+	}
+	fcntl(v,F_SETFL,O_NDELAY);
+	return(v);
+}
+
+int socket_connect_byaddr(union addr * addr)
+{
+	int fd;
+	int tos = IPTOS_LOWDELAY;
+	
+	if ((fd=socket(addr->generic.sa_family,SOCK_STREAM,IPPROTO_TCP))==-1) {
+		return(-1);
+	}
+
+	if (connect(fd,&(addr->generic), sizeof(union addr))) {
+		close(fd);
+		return(-1);
+	}
+	setsockopt(fd,SOL_IP,IP_TOS,&tos,sizeof(tos));
+	return(fd);
+}
+
+/* 
+ * Create a socket connected to a remote host
+ */
+
+int socket_connect(char *hostname, unsigned short port)
+{
+	int fd = -1;
+	struct hostent *host;
+	union addr addr;
+	extern int h_errno;
+
+	host=gethostbyname2(hostname,AF_INET6);
+	if (host != NULL) {
+		fprintf(stderr, "Connecting to '%s' (IPv6)\n", hostname);
+		addr.ipv6.sin6_family=AF_INET6;
+		memcpy(&addr.ipv6.sin6_addr, host->h_addr_list[0], host->h_length);
+		addr.ipv6.sin6_port=htons(port);
+		fd = socket_connect_byaddr(&addr);
+	}
+	if (fd < 0) {
+		host=gethostbyname2(hostname,AF_INET);
+		if (host != NULL) {
+			fprintf(stderr, "Connecting to '%s' (IPv4)\n", hostname);
+			addr.ipv4.sin_family=AF_INET;
+			memcpy(&addr.ipv4.sin_addr, host->h_addr_list[0], host->h_length);
+			addr.ipv4.sin_port=htons(port);
+			fd = socket_connect_byaddr(&addr);
+		}
+	}
+	if (fd < 0) {
+		fprintf(stderr, "Connection to '%s' failed: %s\n", hostname, strerror(errno));
+	}
+	return(fd);
+}
+

Added: branches/newipc3/src/socket.h
===================================================================
--- branches/newipc3/src/socket.h	                        (rev 0)
+++ branches/newipc3/src/socket.h	2007-03-29 19:39:49 UTC (rev 944)
@@ -0,0 +1,7 @@
+/* socket.c */
+
+#define DEFAULT_HOST	"::1"	/* Connect to the loopback address by default */
+#define DEFAULT_PORT	4000	/* Connect to port 4000 by default */
+
+int socket_listen(unsigned short port);
+int socket_connect(char *hostname, unsigned short port);





More information about the mw-devel mailing list