tcp_dos.c
上传用户:ycwykj01
上传日期:2007-01-04
资源大小:1819k
文件大小:11k
源码类别:

网络编程

开发平台:

Unix_Linux

  1. /*
  2.  * Program: MS-DOS TCP/IP routines
  3.  *
  4.  * Author: Mark Crispin
  5.  * Networks and Distributed Computing
  6.  * Computing & Communications
  7.  * University of Washington
  8.  * Administration Building, AG-44
  9.  * Seattle, WA  98195
  10.  * Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date: 11 April 1989
  13.  * Last Edited: 10 June 1999
  14.  *
  15.  * Copyright 1998 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35. static tcptimeout_t tmoh = NIL; /* TCP timeout handler routine */
  36. static long ttmo_read = 0; /* TCP timeouts, in seconds */
  37. static long ttmo_write = 0;
  38. /* TCP/IP manipulate parameters
  39.  * Accepts: function code
  40.  *     function-dependent value
  41.  * Returns: function-dependent return value
  42.  */
  43. void *tcp_parameters (long function,void *value)
  44. {
  45.   switch ((int) function) {
  46.   case SET_TIMEOUT:
  47.     tmoh = (tcptimeout_t) value;
  48.     break;
  49.   case GET_TIMEOUT:
  50.     value = (void *) tmoh;
  51.     break;
  52.   case SET_READTIMEOUT:
  53.     ttmo_read = (long) value;
  54.     break;
  55.   case GET_READTIMEOUT:
  56.     value = (void *) ttmo_read;
  57.     break;
  58.   case SET_WRITETIMEOUT:
  59.     ttmo_write = (long) value;
  60.     break;
  61.   case GET_WRITETIMEOUT:
  62.     value = (void *) ttmo_write;
  63.     break;
  64.   default:
  65.     value = NIL; /* error case */
  66.     break;
  67.   }
  68.   return value;
  69. }
  70. /* TCP/IP open
  71.  * Accepts: host name
  72.  *     contact service name
  73.  *     contact port number
  74.  * Returns: TCP/IP stream if success else NIL
  75.  */
  76. TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
  77. {
  78.   TCPSTREAM *stream = NIL;
  79.   struct sockaddr_in sin;
  80.   int sock;
  81.   char *s,tmp[MAILTMPLEN];
  82.   /* The domain literal form is used (rather than simply the dotted decimal
  83.      as with other Unix programs) because it has to be a valid "host name"
  84.      in mailsystem terminology. */
  85.   sin.sin_family = AF_INET; /* family is always Internet */
  86. /* look like domain literal? */
  87.   if (host[0] == '[' && host[(strlen (host))-1] == ']') {
  88.     strcpy (tmp,host+1); /* yes, copy number part */
  89.     tmp[strlen (tmp)-1] = '';
  90.     if ((sin.sin_addr.s_addr = inet_addr (tmp)) == -1) {
  91.       sprintf (tmp,"Bad format domain-literal: %.80s",host);
  92.       mm_log (tmp,ERROR);
  93.       return NIL;
  94.     }
  95.   }
  96. /* look up host name */
  97.   else if (!lookuphost (&host,&sin)) {
  98.     sprintf (tmp,"Host not found: %s",host);
  99.     mm_log (tmp,ERROR);
  100.     return NIL;
  101.   }
  102. /* copy port number in network format */
  103.   if (!(sin.sin_port = htons (port))) fatal ("Bad port argument to tcp_open");
  104. /* get a TCP stream */
  105.   if ((sock = socket (sin.sin_family,SOCK_STREAM,0)) < 0) {
  106.     sprintf (tmp,"Unable to create TCP socket (%d)",errno);
  107.     mm_log (tmp,ERROR);
  108.     fs_give ((void **) &host);
  109.     return NIL;
  110.   }
  111. /* open connection */
  112.   if (connect (sock,(struct sockaddr *) &sin,sizeof (sin)) < 0) {
  113.     switch (errno) { /* analyze error */
  114.     case ECONNREFUSED:
  115.       s = "Refused";
  116.       break;
  117.     case ENOBUFS:
  118.       s = "Insufficient system resources";
  119.       break;
  120.     case ETIMEDOUT:
  121.       s = "Timed out";
  122.       break;
  123.     default:
  124.       s = "Unknown error";
  125.       break;
  126.     }
  127.     sprintf (tmp,"Can't connect to %.80s,%ld: %s (%d)",host,port,s,errno);
  128.     mm_log (tmp,ERROR);
  129.     close (sock);
  130.     fs_give ((void **) &host);
  131.     return NIL;
  132.   }
  133. /* create TCP/IP stream */
  134.   stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM));
  135.   stream->host = host; /* official host name */
  136.   stream->localhost = cpystr (mylocalhost ());
  137.   stream->port = port; /* port number */
  138.   stream->tcps = sock; /* init socket */
  139.   stream->ictr = 0; /* init input counter */
  140.   return stream; /* return success */
  141. }
  142.   
  143. /* TCP/IP authenticated open
  144.  * Accepts: NETMBX specifier
  145.  *     service name
  146.  *     returned user name buffer
  147.  * Returns: TCP/IP stream if success else NIL
  148.  */
  149. TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf)
  150. {
  151.   return NIL; /* always NIL on DOS */
  152. }
  153. /* TCP/IP receive line
  154.  * Accepts: TCP/IP stream
  155.  * Returns: text line string or NIL if failure
  156.  */
  157. char *tcp_getline (TCPSTREAM *stream)
  158. {
  159.   int n,m;
  160.   char *st,*ret,*stp;
  161.   char c = '';
  162.   char d;
  163. /* make sure have data */
  164.   if (!tcp_getdata (stream)) return NIL;
  165.   st = stream->iptr; /* save start of string */
  166.   n = 0; /* init string count */
  167.   while (stream->ictr--) { /* look for end of line */
  168.     d = *stream->iptr++; /* slurp another character */
  169.     if ((c == '15') && (d == '12')) {
  170.       ret = (char *) fs_get (n--);
  171.       memcpy (ret,st,n); /* copy into a free storage string */
  172.       ret[n] = ''; /* tie off string with null */
  173.       return ret;
  174.     }
  175.     n++; /* count another character searched */
  176.     c = d; /* remember previous character */
  177.   }
  178. /* copy partial string from buffer */
  179.   memcpy ((ret = stp = (char *) fs_get (n)),st,n);
  180. /* get more data from the net */
  181.   if (!tcp_getdata (stream)) return NIL;
  182. /* special case of newline broken by buffer */
  183.   if ((c == '15') && (*stream->iptr == '12')) {
  184.     stream->iptr++; /* eat the line feed */
  185.     stream->ictr--;
  186.     ret[n - 1] = ''; /* tie off string with null */
  187.   }
  188. /* else recurse to get remainder */
  189.   else if (st = tcp_getline (stream)) {
  190.     ret = (char *) fs_get (n + 1 + (m = strlen (st)));
  191.     memcpy (ret,stp,n); /* copy first part */
  192.     memcpy (ret + n,st,m); /* and second part */
  193.     fs_give ((void **) &stp); /* flush first part */
  194.     fs_give ((void **) &st); /* flush second part */
  195.     ret[n + m] = ''; /* tie off string with null */
  196.   }
  197.   return ret;
  198. }
  199. /* TCP/IP receive buffer
  200.  * Accepts: TCP/IP stream
  201.  *     size in bytes
  202.  *     buffer to read into
  203.  * Returns: T if success, NIL otherwise
  204.  */
  205. long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer)
  206. {
  207.   unsigned long n;
  208.   char *bufptr = buffer;
  209.   while (size > 0) { /* until request satisfied */
  210.     if (!tcp_getdata (stream)) return NIL;
  211.     n = min (size,stream->ictr);/* number of bytes to transfer */
  212. /* do the copy */
  213.     memcpy (bufptr,stream->iptr,n);
  214.     bufptr += n; /* update pointer */
  215.     stream->iptr +=n;
  216.     size -= n; /* update # of bytes to do */
  217.     stream->ictr -=n;
  218.   }
  219.   bufptr[0] = ''; /* tie off string */
  220.   return T;
  221. }
  222. /* TCP/IP receive data
  223.  * Accepts: TCP/IP stream
  224.  * Returns: T if success, NIL otherwise
  225.  */
  226. long tcp_getdata (TCPSTREAM *stream)
  227. {
  228.   int i;
  229.   fd_set fds,efds;
  230.   struct timeval tmo;
  231.   time_t t = time (0);
  232.   if (stream->tcps < 0) return NIL;
  233.   while (stream->ictr < 1) { /* if nothing in the buffer */
  234.     time_t tl = time (0); /* start of request */
  235.     tmo.tv_sec = ttmo_read; /* read timeout */
  236.     tmo.tv_usec = 0;
  237.     FD_ZERO (&fds); /* initialize selection vector */
  238.     FD_ZERO (&efds); /* handle errors too */
  239.     FD_SET (stream->tcps,&fds);/* set bit in selection vector */
  240.     FD_SET(stream->tcps,&efds);/* set bit in error selection vector */
  241.     errno = NIL; /* block and read */
  242.     while (((i = select (stream->tcps+1,&fds,0,&efds,ttmo_read ? &tmo : 0))<0)
  243.    && (errno == EINTR));
  244.     if (!i) { /* timeout? */
  245.       time_t tc = time (0);
  246.       if (tmoh && ((*tmoh) (tc - t,tc - tl))) continue;
  247.       else return tcp_abort (stream);
  248.     }
  249.     else if (i < 0) return tcp_abort (stream);
  250.     while (((i = read (stream->tcps,stream->ibuf,BUFLEN)) < 0) &&
  251.    (errno == EINTR));
  252.     if (i < 1) return tcp_abort (stream);
  253.     stream->iptr = stream->ibuf;/* point at TCP buffer */
  254.     stream->ictr = i; /* set new byte count */
  255.   }
  256.   return T;
  257. }
  258. /* TCP/IP send string as record
  259.  * Accepts: TCP/IP stream
  260.  *     string pointer
  261.  * Returns: T if success else NIL
  262.  */
  263. long tcp_soutr (TCPSTREAM *stream,char *string)
  264. {
  265.   return tcp_sout (stream,string,(unsigned long) strlen (string));
  266. }
  267. /* TCP/IP send string
  268.  * Accepts: TCP/IP stream
  269.  *     string pointer
  270.  *     byte count
  271.  * Returns: T if success else NIL
  272.  */
  273. long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size)
  274. {
  275.   int i;
  276.   fd_set fds;
  277.   struct timeval tmo;
  278.   time_t t = time (0);
  279.   if (stream->tcps < 0) return NIL;
  280.   while (size > 0) { /* until request satisfied */
  281.     time_t tl = time (0); /* start of request */
  282.     tmo.tv_sec = ttmo_write; /* write timeout */
  283.     tmo.tv_usec = 0;
  284.     FD_ZERO (&fds); /* initialize selection vector */
  285.     FD_SET (stream->tcps,&fds);/* set bit in selection vector */
  286.     errno = NIL; /* block and write */
  287.     while (((i = select (stream->tcps+1,0,&fds,0,ttmo_write ? &tmo : 0)) < 0)
  288.    && (errno == EINTR));
  289.     if (!i) { /* timeout? */
  290.       time_t tc = time (0);
  291.       if (tmoh && ((*tmoh) (tc - t,tc - tl))) continue;
  292.       else return tcp_abort (stream);
  293.     }
  294.     else if (i < 0) return tcp_abort (stream);
  295.     while (((i = write (stream->tcps,string,size)) < 0) && (errno == EINTR));
  296.     if (i < 0) return tcp_abort (stream);
  297.     size -= i; /* how much we sent */
  298.     string += i;
  299.   }
  300.   return T; /* all done */
  301. }
  302. /* TCP/IP close
  303.  * Accepts: TCP/IP stream
  304.  */
  305. void tcp_close (TCPSTREAM *stream)
  306. {
  307.   tcp_abort (stream); /* nuke the socket */
  308. /* flush host names */
  309.   fs_give ((void **) &stream->host);
  310.   fs_give ((void **) &stream->localhost);
  311.   fs_give ((void **) &stream); /* flush the stream */
  312. }
  313. /* TCP/IP abort stream
  314.  * Accepts: TCP/IP stream
  315.  * Returns: NIL always
  316.  */
  317. long tcp_abort (TCPSTREAM *stream)
  318. {
  319.   if (stream->tcps >= 0) close (stream->tcps);
  320.   stream->tcps = -1;
  321.   return NIL;
  322. }
  323. /* TCP/IP get host name
  324.  * Accepts: TCP/IP stream
  325.  * Returns: host name for this stream
  326.  */
  327. char *tcp_host (TCPSTREAM *stream)
  328. {
  329.   return stream->host; /* return host name */
  330. }
  331. /* TCP/IP get remote host name
  332.  * Accepts: TCP/IP stream
  333.  * Returns: host name for this stream
  334.  */
  335. char *tcp_remotehost (TCPSTREAM *stream)
  336. {
  337.   return stream->host; /* all we can do for now */
  338. }
  339. /* TCP/IP return port for this stream
  340.  * Accepts: TCP/IP stream
  341.  * Returns: port number for this stream
  342.  */
  343. unsigned long tcp_port (TCPSTREAM *stream)
  344. {
  345.   return stream->port; /* return port number */
  346. }
  347. /* TCP/IP get local host name
  348.  * Accepts: TCP/IP stream
  349.  * Returns: local host name
  350.  */
  351. char *tcp_localhost (TCPSTREAM *stream)
  352. {
  353.   return stream->localhost; /* return local host name */
  354. }
  355. /* TCP/IP return canonical form of host name
  356.  * Accepts: host name
  357.  * Returns: canonical form of host name
  358.  */
  359. char *tcp_canonical (char *name)
  360. {
  361.   return name;
  362. }
  363. /* TCP/IP get client host name (server calls only)
  364.  * Returns: client host name
  365.  */
  366. char *tcp_clienthost ()
  367. {
  368.   return "UNKNOWN";
  369. }