[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