flow.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:6k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /* Copyright (c) 1995,1996,1997 NEC Corporation.  All rights reserved.       */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6. /*
  7.  * $Id: flow.c,v 1.31.4.3 1998/03/04 16:13:39 jyou Exp $
  8.  */
  9. /* This file has all the function to do tcp proxying itself.  The only one   */
  10. /* that is visible to the outside world should be HandleTcpConnection.       */
  11. #include "socks5p.h"
  12. #include "daemon.h"
  13. #include "proxy.h"
  14. #include "flow.h"
  15. #include "log.h"
  16. #include "msg.h"
  17. #ifndef INACTIVITY_TIMEOUT
  18. #define INACTIVITY_TIMEOUT 15*60 /* How much inactivity will I tolerate???   */
  19. #endif
  20. static int proxyinturn() {
  21.     static int turn = 0;
  22.     return turn = turn?0:1;
  23. }
  24. static int FlowSetup(S5Packet *buf) {
  25.     char *olddata = buf->data;
  26.     if (buf->data == NULL) {
  27. buf->data = malloc(GENERICBUFSIZE);
  28. if (buf->data) S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Flow Setup: Allocated Buffer");
  29. buf->len  = GENERICBUFSIZE;
  30. buf->off  = 0;
  31.     }
  32.     if (buf->len == buf->off) {
  33. buf->data = realloc(olddata = buf->data, buf->len += GENERICBUFSIZE);
  34. if (buf->data) S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Flow Setup: Grew Buffer");
  35.     }
  36.     if (buf->data == NULL) {
  37. S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Flow Setup: Couldn't allocate buffer space");
  38. if (!olddata) free(olddata);
  39. return -1;
  40.     }
  41.     return 0;
  42. }
  43. int S5TcpFlowRecv(S5IOInfo *iio, S5IOInfo *oio, S5Packet *packet, int *dir) {
  44.     S5IOHandle fdsbits = ((iio->fd > oio->fd)?iio->fd:oio->fd)+1;
  45.     fd_set fds, xfds, bu;
  46.     S5IOInfo *io;
  47.     char *string;
  48.     int n;
  49.     int turn = 1;
  50.     FD_ZERO(&bu);
  51.     if (*dir & S5_DIRECTION_OUT) FD_SET(iio->fd, &bu);
  52.     if (*dir & S5_DIRECTION_IN)  FD_SET(oio->fd, &bu);
  53.     if (FlowSetup(packet) < 0) {
  54. return -1;
  55.     }
  56.     for (fds = bu ; ; fds = bu) {
  57. struct timeval tout;
  58. tout.tv_sec = idletimeout*60;
  59. tout.tv_usec = 0;
  60. if (!FD_ISSET(iio->fd,  &fds) && !FD_ISSET(oio->fd, &fds)) {
  61.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Flow Recv: Neither file descriptor is set");
  62.     return -1;
  63. }
  64.         xfds = fds;
  65. switch (select(fdsbits, &fds, NULL, &xfds, &tout)) {
  66.     case -1:
  67. if (ISSOCKETERROR(EINTR)) continue;
  68. S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Flow Recv: Select failed: %m");
  69. return -1;
  70.     case 0:
  71. S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Flow Recv: Select failed: Inactivity timeout");
  72. return -1;
  73. }
  74. if (FD_ISSET(iio->fd, &xfds) && FD_ISSET(oio->fd, &xfds))
  75.             turn = proxyinturn(); 
  76.         else if (FD_ISSET(iio->fd, &xfds))
  77.             turn = 1;
  78.         else if (FD_ISSET(oio->fd, &xfds))
  79.             turn = 0;
  80.         else if (FD_ISSET(iio->fd, &fds) && FD_ISSET(oio->fd, &fds))
  81.             turn = proxyinturn();
  82.         else if (FD_ISSET(iio->fd, &fds))
  83.             turn = 1;
  84. else if (FD_ISSET(oio->fd, &fds))
  85.             turn = 0;
  86. else {
  87.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Flow Recv: Invalid file descriptor set");
  88.     return -1;
  89. }
  90.         if (turn) {
  91.             *dir = S5_DIRECTION_OUT;
  92.             string = "client";
  93.             io = iio;
  94.         } else {
  95.             *dir = S5_DIRECTION_IN;
  96.             string = "server";
  97.             io = oio;
  98.         }
  99.         packet->oob = 0;
  100.         if (FD_ISSET(io->fd, &xfds))
  101.             (void) ioctl(io->fd, SIOCATMARK, (char *)&packet->oob);
  102. #define RECV_IOFLAGS S5_IOFLAGS_TIMED|S5_IOFLAGS_RESTART
  103. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Flow Recv: Reading from %s socket", string);
  104. switch ((n = S5BufReadPacket(io->fd, io, packet->data + packet->off, packet->oob?1:packet->len - packet->off, 0))) {
  105.     case -1: 
  106. S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING,  0, "Flow Recv: %s Read failed: %m", string);
  107. return -1;
  108.     case 0:
  109. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Flow Recv: %s closed connection", string);
  110. return 0;
  111.     default:
  112. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Flow Recv: Read %d bytes from %s socket", n, string);
  113. packet->off += n;
  114. return n;
  115. }
  116.     }
  117. }
  118. int S5TcpFlowSend(S5IOInfo *iio, S5IOInfo *oio, S5Packet *packet, int *dir) {
  119.     double timerm = (double)idletimeout*60;
  120.     S5IOInfo *io;
  121.     char *string;
  122.     int n;
  123.     switch (*dir) {
  124. case S5_DIRECTION_OUT:
  125.     string = "server";
  126.     io = oio;
  127.     break;
  128. case S5_DIRECTION_IN:
  129.     string = "client";
  130.     io = iio;
  131.     break;
  132. default:
  133.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Flow Send: Invalid direction: %d", *dir);
  134.     return -1;
  135.     }
  136.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Flow Send: Writing %d bytes to %s socket", packet->off, string);    
  137. #define SEND_IOFLAGS S5_IOFLAGS_TIMED|S5_IOFLAGS_RESTART|S5_IOFLAGS_NBYTES
  138.     switch ((n = S5IOSend(io->fd, io, packet->data, packet->off, packet->oob?MSG_OOB:0, SEND_IOFLAGS, &timerm))) {
  139. case -1: 
  140.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Flow Send: %s Write failed: %m", string);
  141.     return -1;
  142. case 0:
  143.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Flow Send: %s closed connection", string);
  144.     return 0;
  145. default:
  146.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Flow Send: Wrote %d bytes to %s", n, string);
  147.     packet->off -= n;
  148.     return n;
  149.     }
  150. }