Short: net_connect()
Date: Fri, 4 Aug 2000 16:23:50 +0200 (MEST)
From: lynx@gaar.nicht.besessen.mit.langen.adressen.bei.pages.de
Type: Feature/Patch
State: New

c) comm.c

ein non-blocking tcp connect() ohne erq - das objekt
wird ganz natrlich mit einem host verbunden und kann
dann ganz wie sonst auch mit write,input_to und co. arbeiten.
brauche ich unbedingt fr meine aktiven psyc connections..

ach ja, was auch noch drin ist, ist das binden einer bestimmten
ip adresse - da scheint aber noch was falsch dran zu sein..  :-/
es tut scheinbar nicht, aber schaden tuts auch nicht.
vielleicht siehst du auf anhieb sogar meinen fehler, that would be cool.

*** origs/comm.c-orig	Sun Jan 16 11:46:19 2000
--- src/comm.c	Mon Jul 10 12:24:12 2000
***************
*** 128,138 ****
  /* if driver is compiled for ERQ demon then include the necessary file
   */
  #ifdef ERQ_DEMON
! #    ifdef ERQ_INCLUDE
! #        include ERQ_INCLUDE
! #    else
! #        include "util/erq/erq.h"
! #    endif
  #endif
  
  /* When no special networking code is needed, define the
--- 128,142 ----
  /* if driver is compiled for ERQ demon then include the necessary file
   */
  #ifdef ERQ_DEMON
! # ifdef ERQ_INCLUDE
! #  include ERQ_INCLUDE
! # else
! #  include "util/erq/erq.h"
! # endif
! # ifdef DEBUG
! #  /* i set this in Makefile even if DEBUG as such is not active   -lynx */
! #  define DEBUG_DNS
! # endif
  #endif
  
  /* When no special networking code is needed, define the
***************
*** 207,212 ****
--- 211,228 ----
     * a 'null format string'.
     */
  
+ static int ipcur = 0;
+ 
+ /* for non-blocking net_connect, Junky, Sept 4 93 */
+ #define MAX_OUTCONN 5
+ struct OutConn {
+ 	struct sockaddr_in target;
+ 	object_t *curr_obj;
+ 	int socket;
+ 	int active;
+ } outconn[MAX_OUTCONN];
+ // int active_outgoing_connections = 0;
+ 
  #ifdef COMM_STAT
  
  /* The statistics were originally introduced to measure the efficiency
***************
*** 400,406 ****
  static void send_do(int);
  static void send_dont(int);
  static void remove_flush_entry(interactive_t *ip);
! static void new_player(SOCKET_T new_socket, struct sockaddr_in *addr, size_t len, int login_port);
  static void add_ip_entry(long addr, char *name);
  
  #ifdef ERQ_DEMON
--- 428,434 ----
  static void send_do(int);
  static void send_dont(int);
  static void remove_flush_entry(interactive_t *ip);
! static void new_player(object_t *receiver, SOCKET_T new_socket, struct sockaddr_in *addr, size_t len, int login_port);
  static void add_ip_entry(long addr, char *name);
  
  #ifdef ERQ_DEMON
***************
*** 547,553 ****
  
  /*-------------------------------------------------------------------------*/
  void
! initialize_host_ip_number (void)
  
  /* Initialise the globals host_ip_number and host_ip_address.
   * Open the UDP port if requested so that it can be used
--- 575,581 ----
  
  /*-------------------------------------------------------------------------*/
  void
! initialize_host_ip_number (const char *bindname)
  
  /* Initialise the globals host_ip_number and host_ip_address.
   * Open the UDP port if requested so that it can be used
***************
*** 561,573 ****
      char *p;
      length_t tmp;
  
!     if (gethostname(host_name, sizeof host_name) == -1) {
!         perror("gethostname");
!         exit(1);
      }
!     hp = gethostbyname(host_name);
      if (!hp) {
!         fprintf(stderr, "%s gethostbyname: unknown host '%s'.\n", time_stamp(), host_name);
          exit(1);
      }
      memset(&host_ip_addr, 0, sizeof host_ip_addr);
--- 589,604 ----
      char *p;
      length_t tmp;
  
!     if (!bindname) {
! 	if (gethostname(host_name, sizeof host_name) == -1) {
! 	    perror("gethostname");
! 	    exit(1);
! 	}
! 	bindname = host_name;
      }
!     hp = gethostbyname(bindname);
      if (!hp) {
!         fprintf(stderr, "%s gethostbyname: unknown host '%s'.\n", time_stamp(), bindname);
          exit(1);
      }
      memset(&host_ip_addr, 0, sizeof host_ip_addr);
***************
*** 715,720 ****
--- 746,754 ----
      length_t tmp;
      int i;
  
+     /* non blocking net_connect -Junky */
+     for (i=0; i<MAX_OUTCONN; i++) outconn[i].active=0;
+ 
      /* Initialize the telnet machine unless mudlib_telopts() already
       * did that.
       */
***************
*** 752,758 ****
              }
              if (bind(sos[i], (struct sockaddr *)&host_ip_addr, sizeof host_ip_addr) == -1) {
                  if (errno == EADDRINUSE) {
!                     fprintf(stderr, "%s Socket already bound!\n", time_stamp());
                      debug_message("%s Socket already bound!\n", time_stamp());
                      exit(errno);
                  } else {
--- 786,792 ----
              }
              if (bind(sos[i], (struct sockaddr *)&host_ip_addr, sizeof host_ip_addr) == -1) {
                  if (errno == EADDRINUSE) {
!                     fprintf(stderr, "%s Port %d on %s not available!\n", time_stamp(), port_numbe
rs[i], domain_name);
                      debug_message("%s Socket already bound!\n", time_stamp());
                      exit(errno);
                  } else {
***************
*** 1562,1582 ****
  
                              int32 net_addr;
  
                              if (msglen < 13 || rp[msglen-1]) {
! #ifdef DEBUG
                                if (msglen == 12) {
                                  if (d_flag > 1)
!                                   debug_message("%s Host lookup failed\n"
!                                                , time_stamp());
                                } else {
                                  debug_message("%s Bogus reverse name lookup.\n"
                                               , time_stamp());
                                }
! #endif
                              } else {
!                                 memcpy((char*)&net_addr, rp+8, 4);
!                                 add_ip_entry(net_addr, rp+12);
!                             }
                              continue;
                          }
                          else
--- 1596,1625 ----
  
                              int32 net_addr;
  
+ 			    memcpy((char*)&net_addr, rp+8, 4);
                              if (msglen < 13 || rp[msglen-1]) {
! # ifdef DEBUG_DNS
                                if (msglen == 12) {
+ 				/* this may look strange but it actually outputs the ip number */
                                  if (d_flag > 1)
!                                   debug_message("%s Host lookup failed for %s\n"
!                                                , time_stamp(), dns_lookup(net_addr));
                                } else {
                                  debug_message("%s Bogus reverse name lookup.\n"
                                               , time_stamp());
                                }
! # endif
                              } else {
! # ifdef DEBUG_DNS
! 			      char* ipn;
! 			      ipn = dns_lookup(net_addr);
! # endif
!                               add_ip_entry(net_addr, rp+12);
! # ifdef DEBUG_DNS
! 			      fprintf(stderr, "%s DNS/erq: %s resolved as %s\n", time_stamp(),
! 				      ipn, dns_lookup(net_addr));
! # endif
! 			    }
                              continue;
                          }
                          else
***************
*** 1667,1673 ****
                      new_socket = accept(sos[i], (struct sockaddr *)&addr
                                                , &length);
                      if ((int)new_socket != -1)
!                         new_player(new_socket, &addr, (size_t)length
                                    , port_numbers[i]);
                      else if ((int)new_socket == -1
                        && errno != EWOULDBLOCK && errno != EINTR
--- 1710,1716 ----
                      new_socket = accept(sos[i], (struct sockaddr *)&addr
                                                , &length);
                      if ((int)new_socket != -1)
!                         new_player(NULL, new_socket, &addr, (size_t)length
                                    , port_numbers[i]);
                      else if ((int)new_socket == -1
                        && errno != EWOULDBLOCK && errno != EINTR
***************
*** 2214,2221 ****
  }
  
  /*-------------------------------------------------------------------------*/
  static void
! new_player (SOCKET_T new_socket, struct sockaddr_in *addr, size_t addrlen
  #if !defined(ACCESS_CONTROL)
             , int login_port UNUSED
  #else
--- 2257,2320 ----
  }
  
  /*-------------------------------------------------------------------------*/
  static void
! new_player (object_t *ob, SOCKET_T new_socket,
! 	    struct sockaddr_in *addr, size_t addrlen
  #if !defined(ACCESS_CONTROL)
             , int login_port UNUSED
  #else
***************
*** 2248,2254 ****
  
      int   i;             /* Index of free slot in all_players[] */
      char *message;       /* Failure message */
-     object_t *ob;   /* Login object */
      svalue_t *ret;  /* LPC call results */
      interactive_t *new_interactive;
                           /* The new interactive structure */
--- 2347,2352 ----
***************
*** 2398,2414 ****
      /* The player object has one extra reference. */
      ref_object(master_ob, "new_player");
  
!     /* Call master->connect() and evaluate the result.
!      */
!     ret = apply_master_ob(STR_CONNECT, 0);
!     if (new_interactive != O_GET_INTERACTIVE(master_ob))
!         return;
!     if (ret == NULL
!      || ret->type != T_OBJECT
!      || (ob = ret->u.ob, O_IS_INTERACTIVE(ob)))
!     {
!         remove_interactive(master_ob);
!         return;
      }
      command_giver = master_ob;
      add_message(message_flush);
--- 2496,2520 ----
      /* The player object has one extra reference. */
      ref_object(master_ob, "new_player");
  
!     if (ob) {
! 	/* treat net_connect objects directly without asking master
! 	 * this solution isn't really beautiful but i don't feel like
! 	 * digging too deep into the interiors of the driver	--symlynX
! 	 */
! 	if (O_IS_INTERACTIVE(ob)) remove_interactive(ob);
!     } else {
! 	/* Call master->connect() and evaluate the result.
! 	 */
! 	ret = apply_master_ob(STR_CONNECT, 0);
! 	if (new_interactive != O_GET_INTERACTIVE(master_ob))
! 	    return;
! 	if (ret == NULL
! 	 || ret->type != T_OBJECT
! 	 || (ob = ret->u.ob, O_IS_INTERACTIVE(ob)))
! 	{
! 	    remove_interactive(master_ob);
! 	    return;
! 	}
      }
      command_giver = master_ob;
      add_message(message_flush);
***************
*** 5385,5388 ****
--- 5504,5619 ----
  }
  
  /***************************************************************************/
+ 
+ /* NEMESIS net_connect extension by snake and lynx 1992,
+  * greatly improved by junky 1993
+  */
+ int net_connect(targetname, targetport) char* targetname; int targetport; {
+ 	int d, n, ret;
+ 	struct hostent *h;
+ 	struct sockaddr_in target;
+ 	object_t *user;
+ 
+ 	target.sin_port = htons(targetport);
+ 	h = gethostbyname(targetname);
+ 	target.sin_addr.s_addr = h ? ** (int **) (h -> h_addr_list)
+ 		: inet_addr(targetname);
+ 	if (!target.sin_addr.s_addr) return -1;
+ 	target.sin_family = h ? h -> h_addrtype : AF_INET;
+ 	d = socket (target.sin_family, SOCK_STREAM, 0);
+ 	if (d == -1) {
+ 		perror ("socket");
+ 		return errno;
+ 	}
+ 	/* non-blocking net connect, Junky, Sept 4 93 */
+ 	fcntl(d, F_SETFL, O_NDELAY);
+ 	n=1;
+ 	ioctl(d, FIONBIO, &n);
+ 	ret = connect(d, (struct sockaddr *) &target, sizeof(target));
+ 	if (ret == -1) {
+ 		switch(errno) {
+ 		case EINPROGRESS: /* no immediate connection - store everything */
+ 			n=0;
+ 			while (n<MAX_OUTCONN) {
+ 				if (!outconn[n].active) {
+ 					outconn[n].socket=d;
+ 					outconn[n].target=target;
+ 					outconn[n].curr_obj=current_object;
+ 					outconn[n].active=1;
+ 					// active_outgoing_connections++;
+ 					n=MAX_OUTCONN;
+ 				}
+ 				n++;
+ 			}
+ 			if (n==MAX_OUTCONN) { /* all descriptors occupied */
+ 				close(d);
+ 				return EMFILE;
+ 			}
+ 			return 0;
+ 		default: /* error with connection */
+ 			close (d);
+ 			return errno;
+ 		}
+ 	}
+ 	user = command_giver;
+ 	// new_interactive(current_object, d, &target, sizeof(target));
+ 	new_player(current_object, d, &target, sizeof(target), 0);
+ 		   // ntohs(target.sin_port));
+ 	command_giver = user;
+ 	return 0;
+ }
+ 
+ void check_for_out_connections() {
+ 	int i, ret;
+ 	object_t *user;
+ 
+ 	// if (active_outgoing_connections <= 0) return;
+ 	for (i=0; i<MAX_OUTCONN; i++) {
+ 		if (!outconn[i].active) continue;
+ 		ret = connect(outconn[i].socket, (struct sockaddr*) &outconn[i].target,
+ 			sizeof(outconn[i].target));
+ 		if (ret == -1) {
+ 			switch(errno) {
+ 			case EALREADY: /* still trying */
+ 				continue;
+ 			case EISCONN: /* we are connected! */
+ 				break;
+ 			default: /* error with connection */
+ 				if (!outconn[i].curr_obj || 
+ 					(outconn[i].curr_obj)->flags & O_DESTRUCTED) {
+ 					/* well, got no connection anyway... */
+ 				fprintf(stderr, 
+ 					"net_connect: no connection on destructed object!\n");
+ 				}
+ 				else {
+ 					push_number(-1);
+ 					(void) apply("logon", outconn[i].curr_obj, 1);
+ 				}
+ 				outconn[i].active=0;
+ 				// active_outgoing_connections--;
+ 				continue;
+ 			}
+ 		}
+ 		/* connection successful */
+ 		if (!outconn[i].curr_obj ||
+ 			(outconn[i].curr_obj)->flags & O_DESTRUCTED) {
+ 			/* bad luck - should not happen :-( */
+ 			fprintf(stderr, 
+ 			    "net_connect: connection on destructed object!\n");
+ 		}
+ 		else {
+ 			user = command_giver;
+ 
+ 			new_player(outconn[i].curr_obj, outconn[i].socket,
+ 			   &outconn[i].target, sizeof(outconn[i].target), 0);
+ 				// ntohs(outconn[i].target.sin_port));
+ //			new_interactive(outconn[i].curr_obj, outconn[i].socket,
+ //				&outconn[i].target, sizeof(outconn[i].target));
+ 			command_giver = user;
+ 		}
+ 		outconn[i].active=0;
+ 	}
+ }
+ 
+ /* end non-blocking net_connect */
  


