msg.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:9k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /* Copyright (c) 1995,1996,1997 NEC Corporation. All rights reserved. */
- /* */
- /* The redistribution, use and modification in source or binary forms of */
- /* this software is subject to the conditions set forth in the copyright */
- /* document ("Copyright") included with this distribution. */
- /*
- * $Id: msg.c,v 1.30.2.1.2.3 1998/07/17 19:57:01 wlu Exp $
- */
- /* This file contains functions support reliable message transport under any */
- /* (UDP or TCP) protocol. */
- #include "socks5p.h"
- #include "buffer.h"
- #include "block.h"
- #include "msg.h"
- #include "log.h"
- int S5IORecv(S5IOHandle fd, S5IOInfo *info, char *buf, int size, int ioflags, int libflags, double *timerm) {
- int nr, sval, rlen = size;
- struct timeval sv, *svpt;
- fd_set fds, b;
- #ifdef STRICT_TIMEOUT
- struct timeval ts, te;
- #endif
- if (libflags & S5_IOFLAGS_TIMED && !timerm) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IORecv: NULL timeout pointer passed");
- SETSOCKETERROR(ETIMEDOUT);
- return -1;
- }
- if ((libflags & S5_IOFLAGS_NBYTES) && !(libflags & S5_IOFLAGS_RESTART)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IORecv: Warning: Cannot reliably read n bytes and not handle restarts");
- }
- /* We may have read in some stuff and buffered it. Rather than replace */
- /* select, lets just read the stuff *out* of the buffer first... */
- while (1) {
- if ((sval = S5BufCheckData(fd, info)) < 0) return -1;
- if (sval == 0) break;
- if ((nr = S5BufReadPacket(fd, info, buf, rlen, ioflags)) < 0) return -1;
- if (nr == 0) return (size - rlen);
- rlen -= nr; buf += nr;
- if (!(libflags & S5_IOFLAGS_NBYTES)) return nr;
- if (rlen == 0) return size;
- }
- /* Read again and again until we have an error, we run out of time, or */
- /* we just read all that we wanted to. If STRICT_TIMEOUT is defined, */
- /* subtract the amount of time we've spent at each point form the time */
- /* we are allowing *total*...This is kind of expensive...An alternative, */
- /* which has nearly the same consequences is is to spend that amount of */
- /* time *each* read. If the data is too interspersed, it will die... */
- FD_ZERO(&b);
- FD_SET(fd, &b);
- for (fds = b; rlen > 0; fds = b) {
- if (libflags & S5_IOFLAGS_TIMED) {
- sv.tv_sec = (int)*timerm;
- sv.tv_usec = (int)((*timerm - (double)sv.tv_sec) * 1000000.0);
- #ifdef STRICT_TIMEOUT
- if (gettimeofday(&ts, NULL) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IORecv: gettimeofday failed: %m");
- SETSOCKETERROR(ETIMEDOUT);
- goto interrupted;
- }
- #endif
- } else {
- sv.tv_sec = 0;
- sv.tv_usec = 0;
- }
- if (libflags & S5_IOFLAGS_TIMED) svpt = &sv;
- else if (ISNBLOCK(fd) && !(libflags & S5_IOFLAGS_NBYTES)) svpt = &sv;
- else svpt = NULL;
- if ((sval = REAL(select)(fd + 1, &fds, NULL, NULL, svpt)) == 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "S5IORecv: select failed: Timed out");
- if (libflags & S5_IOFLAGS_TIMED) SETSOCKETERROR(ETIMEDOUT);
- #if defined(sun) && !defined(__svr4__)
- else SETSOCKETERROR(EWOULDBLOCK);
- #else
- else SETSOCKETERROR(EAGAIN);
- #endif
- sval = -1;
- goto interrupted;
- }
- #ifdef STRICT_TIMEOUT
- if (libflags & S5_IOFLAGS_TIMED) {
- if (gettimeofday(&te, NULL) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IORecv: gettimeofday failed: %m");
- SETSOCKETERROR(ETIMEDOUT);
- sval = -1;
- goto interrupted;
- }
- *timerm -= (te.tv_sec - ts.tv_sec);
- *timerm -= (te.tv_usec - ts.tv_usec)/1000000.0;
- if (*timerm < 0.0) *timerm = 0.0;
- }
- #endif
- if (sval < 0) {
- if (ISSOCKETERROR(EINTR) && libflags & S5_IOFLAGS_RESTART) continue;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IORecv: Select failed: %m");
- goto interrupted;
- }
- while (rlen > 0) {
- switch ((sval = S5BufCheckPacket(fd, info))) {
- case 0:
- case -1: goto interrupted;
- default: break;
- }
- /* packet is not available... */
- if (sval < 0) break;
- if ((nr = S5BufReadPacket(fd, info, buf, rlen, ioflags)) <= 0) {
- sval = nr;
- goto interrupted;
- }
- if (!(libflags & S5_IOFLAGS_NBYTES)) return nr;
- rlen -= nr;
- buf += nr;
- }
- if (sval < 0 && !(libflags & S5_IOFLAGS_NBYTES)) {
- sval = -1;
- goto interrupted;
- }
- }
- return size;
- interrupted:
- /* We read some data in, but we were interrupted and we aren't supposed */
- /* to restart... So we have to store what we've read so far in info... */
- if (S5BufUnreadPacket(info, buf-(size-rlen), size-rlen)) {
- /* Nowhere to store what we've read... Bummer... */
- }
- return sval;
- }
- int S5IOSend(S5IOHandle fd, S5IOInfo *info, char *buf, int size, int flags, int libflags, double *timerm) {
- struct timeval sv, *svpt;
- int nw, wlen, sval;
- fd_set fds, b;
- #ifdef STRICT_TIMEOUT
- struct timeval ts, te;
- #endif
- if (libflags & S5_IOFLAGS_TIMED && !timerm) {
- SETSOCKETERROR(ETIMEDOUT);
- return -1;
- }
- if ((libflags & S5_IOFLAGS_NBYTES) && !(libflags & S5_IOFLAGS_RESTART)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IOSend: Warning: Cannot reliably write n bytes and not handle restarts");
- }
- FD_ZERO(&b);
- FD_SET(fd, &b);
- for (fds = b, wlen = size; wlen > 0; fds = b) {
- if (libflags & S5_IOFLAGS_TIMED) {
- sv.tv_sec = (int)*timerm;
- sv.tv_usec = (int)((*timerm - (double)sv.tv_sec) * 1000000.0);
- #ifdef STRICT_TIMEOUT
- if (gettimeofday(&ts, NULL) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IOSend: gettimeofday failed: %m");
- SETSOCKETERROR(ETIMEDOUT);
- return -1;
- }
- #endif
- } else {
- sv.tv_sec = 0;
- sv.tv_usec = 0;
- }
- if (libflags & S5_IOFLAGS_TIMED) svpt = &sv;
- else if (ISNBLOCK(fd) && !(libflags & S5_IOFLAGS_NBYTES)) svpt = &sv;
- else svpt = NULL;
- if ((sval = REAL(select)(fd + 1, NULL, &fds, NULL, svpt)) == 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "S5IOSend: select failed: Timed out");
- if (libflags & S5_IOFLAGS_TIMED) SETSOCKETERROR(ETIMEDOUT);
- #if defined(sun) && !defined(__svr4__)
- else SETSOCKETERROR(EWOULDBLOCK);
- #else
- else SETSOCKETERROR(EAGAIN);
- #endif
- return -1;
- }
- #ifdef STRICT_TIMEOUT
- if (libflags & S5_IOFLAGS_TIMED) {
- if (gettimeofday(&te, NULL) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IOSend: gettimeofday failed: %m");
- SETSOCKETERROR(ETIMEDOUT);
- return -1;
- }
- *timerm -= (te.tv_sec - ts.tv_sec);
- *timerm -= (te.tv_usec - ts.tv_usec)/1000000.0;
- if (*timerm < 0.0) *timerm = 0.0;
- }
- #endif
- if (sval < 0) {
- if (ISSOCKETERROR(EINTR) && libflags & S5_IOFLAGS_RESTART) continue;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IOSend: Select failed: %m");
- return -1;
- }
- do {
- if ((nw = S5BufWritePacket(fd, info, buf, wlen, flags)) > 0) break;
- if (ISSOCKETERROR(EINTR) && !(libflags & S5_IOFLAGS_RESTART)) break;
- if ((ISSOCKETERROR(EWOULDBLOCK) || ISSOCKETERROR(EAGAIN)) && !(libflags & S5_IOFLAGS_NBYTES)) break;
- nw = 0;
- } while (S5IOCheck(fd) >= 0);
- if (nw < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IOSend: failed: %m");
- return nw;
- }
- if (nw == 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IOSend: peer closed");
- SETSOCKETERROR(EPIPE);
- return -1;
- }
- if (!(libflags & S5_IOFLAGS_NBYTES)) return nw;
- wlen -= nw;
- buf += nw;
- }
- return size;
- }
- /* See what's going on with a socket -- is the connection still valid? */
- int S5IOCheck(S5IOHandle fd) {
- struct timeval tv = { 0, 0 };
- fd_set rfds, b;
- char dummy;
- int sv, n;
- FD_ZERO(&b);
- FD_SET(fd, &b);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "S5IOCheck: Checking socket status");
- /* Poll the file descriptor real quick, and see what comes back... */
- while (1) {
- rfds = b;
- switch ((sv = REAL(select)(fd+1, &rfds, NULL, NULL, &tv))) {
- case 1:
- /* Something happened -- either an error or data, ok to recv */
- n = RECVSOCKET(fd, &dummy, 1, MSG_PEEK);
- if (n < 0 && ISSOCKETERROR(EINTR)) continue;
- else if (n <= 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "S5IOCheck: recv failed: %m");
- return -1;
- }
- /* fallthrough -- there is real data there... */
- case 0:
- /* Nothing's happening -- no error, all's ok. */
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "S5IOCheck: ok");
- return sv;
- default:
- /* Not a valid socket (?). */
- if (ISSOCKETERROR(EINTR)) continue;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "S5IOCheck: select failed: %m");
- return -1;
- }
- }
- }