udp.c 4.86 KB
Newer Older
Per Cederqvist's avatar
Per Cederqvist committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
/*
** udp.c                             A small ISC subsystem demo program
**
** Copyright (c) 1992 Peter Eriksson and Per Cederqvist of the
**                    Lysator Academic Computer Association.
**
** history:
** 910306 pen      initial coding
** 920211 pen      code cleaned up
*/

#include <stdio.h>
#include <errno.h>

/*
** Could do a "#define ISC_UDGTYPE foobar" to change the type of
** the (IscSession) 'udg' member pointer type from "void *" to "foobar *".
*/
#include <isc.h>


extern void abort(void);

static IscConfig cfg =
{
  1005,
  {
    1001,
    { -1, -1, -1, -1, -1 }
  },
  {
    1001
  }
};

#define TIMEOUT    30000    /* 30 seconds */

Perror(char *msg)
{
  perror(msg);
  exit(1);
}

void
main(int argc, char *argv[])
{
  IscMaster   * mcb;   /* ISC master control block */
  IscSession  * scb;   /* ISC session control block */
  IscSession  * tty;   /* ISC session control block */
  IscEvent    * ecb;   /* ISC event control block */


  if (argc < 2)
    exit(1);

  puts("Beginning operation...");
  
  /*
  ** Initialize the ISC subsystem, create a Master Control Block
  */
  if ((mcb = isc_initialize(&cfg)) == NULL)
    Perror("isc_initialize");

  puts("ISC initialized.");

  if (argc > 2)
  {
    /* Client connection */
    
    /*
     ** Establish a TCP session to a remote service (IRC)
     */
    if ((scb = isc_openudp(mcb, argv[1], argv[2])) == NULL)
      Perror("isc_openudp");

    if ((tty = isc_openfd(mcb, 0)) == NULL)
      Perror("isc_openfd(tty)");
    
    puts("Connection initiated.");
  }
  else
  {
    /*
     ** Enable remote connection attempts at port "argv[1]"
     */
    if (isc_listenudp(mcb, NULL, argv[1]) == 0)
      Perror("isc_listenudp");
    puts("Listening port installed.");
  }


  puts("entering main event loop...");
  
  /*
  ** Handle all events
  */
  while (ecb = isc_getnextevent(mcb, TIMEOUT))
  {
    switch (ecb->event)
    {
      case ISC_EVENT_CONNECTED:
        puts("Server connection established.");
	break;
	
      case ISC_EVENT_REJECTED:
        puts("Server connection rejected.");
	isc_destroy(mcb, scb);
	exit(0);
	
      case ISC_EVENT_ERROR: /* ISC subsystem error */
	fprintf(stderr, "ISC-ERROR: errno = %d", errno);
	if (ecb->msg)
	  fprintf(stderr, " (%s)", ecb->msg->buffer);
	putc('\n', stderr);

	/*
	** Should probably do something more sensible than
	** just finishing off the session
	*/
	if (ecb->session)
	  isc_destroy(mcb, ecb->session);
	break;

      case ISC_EVENT_TIMEOUT: /* Timeout limit reached */
	puts("*** Timeout ***");
	break;

      case ISC_EVENT_LOGIN: /* New client requesting connection */
	{
	  /*
	  ** THIS SHOULD NORMALLY NEVER HAPPEN FOR UDP SESSIONS
	  */
	  char laddr[256];
	  char lserv[256];
	  char raddr[256];
	  char rserv[256];
	  
	  fetch_address(ecb->session->info.tcp.raddr,
			raddr,
			sizeof(raddr)-1,
			rserv,
			sizeof(rserv)-1);
	  
	  fetch_address(ecb->session->info.tcp.laddr,
			laddr,
			sizeof(laddr)-1,
			lserv,
			sizeof(lserv)-1);
	  
	  printf("New session #%d on %s/%s connecting from: %s/%s\n",
		 ecb->session,
		 laddr, lserv,
		 raddr, rserv);
	
	  /*
	  ** Here we could assign the 'ecb->session->udg' member some
	  ** arbitrary value to be used later by our own routines
	  */
	}
	break;

      case ISC_EVENT_LOGOUT: /* Client closed connection */
	if (ecb->session == scb)
	{
	  printf("Server disconnecting\n");
	  exit(0);
	}
	else
	  printf("Client #%d disconnecting\n", ecb->session);

	/*
	** Deallocate the storage reserved for the session
	*/
	isc_destroy(mcb, ecb->session);
	break;

      case ISC_EVENT_MESSAGE: /* Message from client or server */
	if (ecb->session == scb)
	  printf("Message from server: '%s'\n", ecb->msg->buffer);
	else if (ecb->session == tty)
	  isc_send(scb, isc_copymsg(ecb->msg));
	else
	{
	  IscMessage *msg;
	  char raddr[256];
	  char rserv[256];

	  fetch_address(ecb->msg->address,
			raddr,
			sizeof(raddr)-1,
			rserv,
			sizeof(rserv)-1);
	  
	  printf("Message from client #%d (%s/%s):\n%s",
		 ecb->session,
		 raddr, rserv,
		 ecb->msg->buffer);
	  fflush(stdout);
	  
	  /*
	  ** Reply with some text to the client
	  */
	  msg = isc_mkstrmsg("Ok, got it via UDP\n\r");
	  isc_sendto(ecb->session,
		     ecb->msg->address,
		     msg);
	  
	  isc_flush(ecb->session);
	}
	break;

      default: /* NOTREACHED - OR SHOULDN'T BE ATLEAST :-) */
	Perror("NOTREACHED");
    }

    /*
    ** Finished with the event, lets get rid of it
    */
    isc_dispose(ecb);
  }

  /* NOTREACHED - I THINK ... */
  Perror("SHUTDOWN");
}


const char *strerror(int num)
{
  static char foo[256];

  sprintf(foo, "Error #%d", num);
  return foo;
}

fetch_address(IscAddress *ia,
	      char *host,
	      int hlen,
	      char *port,
	      int plen)
{
  char *cp;


  cp = isc_gethostname(ia, host, hlen);
  if (!cp)
    isc_getipnum(ia, host, hlen);

  cp = isc_getservice(ia, port, plen, ISC_TYPE_TCP);
  if (!cp)
    sprintf(port, "%d", isc_getportnum(ia));
}