⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockfilt.c

📁 THIS IS HTTP CURL Example
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** *                                  _   _ ____  _ *  Project                     ___| | | |  _ \| | *                             / __| | | | |_) | | *                            | (__| |_| |  _ <| |___ *                             \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id: sockfilt.c,v 1.38 2007-10-09 23:21:29 yangtse Exp $ ***************************************************************************//* Purpose * * 1. Accept a TCP connection on a custom port (ipv4 or ipv6), or connect *    to a given (localhost) port. * * 2. Get commands on STDIN. Pass data on to the TCP stream. *    Get data from TCP stream and pass on to STDOUT. * * This program is made to perform all the socket/stream/connection stuff for * the test suite's (perl) FTP server. Previously the perl code did all of * this by its own, but I decided to let this program do the socket layer * because of several things: * * o We want the perl code to work with rather old perl installations, thus *   we cannot use recent perl modules or features. * * o We want IPv6 support for systems that provide it, and doing optional IPv6 *   support in perl seems if not impossible so at least awkward. * * o We want FTP-SSL support, which means that a connection that starts with *   plain sockets needs to be able to "go SSL" in the midst. This would also *   require some nasty perl stuff I'd rather avoid. * * (Source originally based on sws.c) */#include "setup.h" /* portability help from the lib directory */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <signal.h>#include <time.h>#include <ctype.h>#include <sys/time.h>#include <sys/types.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#ifdef _XOPEN_SOURCE_EXTENDED/* This define is "almost" required to build on HPUX 11 */#include <arpa/inet.h>#endif#ifdef HAVE_NETDB_H#include <netdb.h>#endif#define ENABLE_CURLX_PRINTF/* make the curlx header define all printf() functions to use the curlx_*   versions instead */#include "curlx.h" /* from the private lib dir */#include "getpart.h"#include "inet_pton.h"#include "util.h"/* include memdebug.h last */#include "memdebug.h"#define DEFAULT_PORT 8999#ifndef DEFAULT_LOGFILE#define DEFAULT_LOGFILE "log/sockfilt.log"#endif#ifdef SIGPIPEstatic volatile int sigpipe;  /* Why? It's not used */#endifconst char *serverlogfile = (char *)DEFAULT_LOGFILE;static void lograw(unsigned char *buffer, ssize_t len){  char data[120];  ssize_t i;  unsigned char *ptr = buffer;  char *optr = data;  ssize_t width=0;  for(i=0; i<len; i++) {    switch(ptr[i]) {    case '\n':      sprintf(optr, "\\n");      width += 2;      optr += 2;      break;    case '\r':      sprintf(optr, "\\r");      width += 2;      optr += 2;      break;    default:      sprintf(optr, "%c", (ISGRAPH(ptr[i]) || ptr[i]==0x20) ?ptr[i]:'.');      width++;      optr++;      break;    }    if(width>60) {      logmsg("'%s'", data);      width = 0;      optr = data;    }  }  if(width)    logmsg("'%s'", data);}#ifdef SIGPIPEstatic void sigpipe_handler(int sig){  (void)sig; /* prevent warning */  sigpipe = 1;}#endifchar use_ipv6=FALSE;unsigned short port = DEFAULT_PORT;unsigned short connectport = 0; /* if non-zero, we activate this mode */enum sockmode {  PASSIVE_LISTEN,    /* as a server waiting for connections */  PASSIVE_CONNECT,   /* as a server, connected to a client */  ACTIVE,            /* as a client, connected to a server */  ACTIVE_DISCONNECT  /* as a client, disconnected from server */};/*  sockfdp is a pointer to an established stream or CURL_SOCKET_BAD  if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must  accept()*/static int juggle(curl_socket_t *sockfdp,                  curl_socket_t listenfd,                  enum sockmode *mode){  struct timeval timeout;  fd_set fds_read;  fd_set fds_write;  fd_set fds_err;  curl_socket_t sockfd;  curl_socket_t maxfd;  ssize_t rc;  ssize_t nread_stdin;  ssize_t nread_socket;  ssize_t bytes_written;  ssize_t buffer_len; /* 'buffer' is this excessively large only to be able to support things like    test 1003 which tests exceedingly large server response lines */  unsigned char buffer[17010];  char data[16];  timeout.tv_sec = 120;  timeout.tv_usec = 0;  FD_ZERO(&fds_read);  FD_ZERO(&fds_write);  FD_ZERO(&fds_err);  FD_SET(fileno(stdin), &fds_read);  switch(*mode) {  case PASSIVE_LISTEN:    /* server mode */    sockfd = listenfd;    /* there's always a socket to wait for */    FD_SET(sockfd, &fds_read);    maxfd = sockfd;    break;  case PASSIVE_CONNECT:    sockfd = *sockfdp;    if(CURL_SOCKET_BAD == sockfd) {      /* eeek, we are supposedly connected and then this cannot be -1 ! */      logmsg("socket is -1! on %s:%d", __FILE__, __LINE__);      maxfd = 0; /* stdin */    }    else {      /* there's always a socket to wait for */      FD_SET(sockfd, &fds_read);      maxfd = sockfd;    }    break;  case ACTIVE:    sockfd = *sockfdp;    /* sockfd turns CURL_SOCKET_BAD when our connection has been closed */    if(CURL_SOCKET_BAD != sockfd) {      FD_SET(sockfd, &fds_read);      maxfd = sockfd;    }    else {      logmsg("No socket to read on");      maxfd = 0;    }    break;  case ACTIVE_DISCONNECT:    logmsg("disconnected, no socket to read on");    maxfd = 0;    sockfd = CURL_SOCKET_BAD;    break;  } /* switch(*mode) */  do {    rc = select(maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);  } while((rc == -1) && (SOCKERRNO == EINTR));  switch(rc) {  case -1:    return FALSE;  case 0: /* timeout! */    return TRUE;  }  if(FD_ISSET(fileno(stdin), &fds_read)) {    /* read from stdin, commands/data to be dealt with and possibly passed on       to the socket       protocol:       4 letter command + LF [mandatory]       4-digit hexadecimal data length + LF [if the command takes data]       data                       [the data being as long as set above]       Commands:       DATA - plain pass-thru data    */    nread_stdin = read(fileno(stdin), buffer, 5);    if(5 == nread_stdin) {      logmsg("Received %c%c%c%c (on stdin)",             buffer[0], buffer[1], buffer[2], buffer[3] );      if(!memcmp("PING", buffer, 4)) {        /* send reply on stdout, just proving we are alive */        write(fileno(stdout), "PONG\n", 5);      }      else if(!memcmp("PORT", buffer, 4)) {        /* Question asking us what PORT number we are listening to.           Replies to PORT with "IPv[num]/[port]" */        sprintf((char *)buffer, "IPv%d/%d\n", use_ipv6?6:4, (int)port);        buffer_len = (ssize_t)strlen((char *)buffer);        snprintf(data, sizeof(data), "PORT\n%04x\n", buffer_len);        write(fileno(stdout), data, 10);        write(fileno(stdout), buffer, buffer_len);      }      else if(!memcmp("QUIT", buffer, 4)) {        /* just die */        logmsg("quits");        return FALSE;      }      else if(!memcmp("DATA", buffer, 4)) {        /* data IN => data OUT */        if(5 != read(fileno(stdin), buffer, 5))          return FALSE;        buffer[5] = '\0';        buffer_len = (ssize_t)strtol((char *)buffer, NULL, 16);        if (buffer_len > (ssize_t)sizeof(buffer)) {          logmsg("Buffer size %d too small for data size %d",                    (int)sizeof(buffer), buffer_len);          return FALSE;        }        logmsg("> %d bytes data, server => client", buffer_len);        if(buffer_len > (ssize_t)sizeof(buffer)) {          logmsg("ERROR: %d bytes of data does not fit within the %d "                 "bytes buffer", buffer_len, sizeof(buffer));          return FALSE;        }        /*         * To properly support huge data chunks, we need to repeat the call         * to read() until we're done or it fails.         */        nread_stdin = 0;        do {          /* get data in the buffer at the correct position */          rc = read(fileno(stdin), &buffer[nread_stdin],                    buffer_len - nread_stdin);          logmsg("read %d bytes", rc);          if(rc <= 0)            return FALSE;          nread_stdin += rc;        } while (nread_stdin < buffer_len);        lograw(buffer, buffer_len);        if(*mode == PASSIVE_LISTEN) {          logmsg("*** We are disconnected!");          write(fileno(stdout), "DISC\n", 5);        }        else {          /* send away on the socket */          bytes_written = swrite(sockfd, buffer, buffer_len);          if(bytes_written != buffer_len) {            logmsg("Not all data was sent. Bytes to send: %d sent: %d",                    buffer_len, bytes_written);          }        }      }      else if(!memcmp("DISC", buffer, 4)) {        /* disconnect! */        write(fileno(stdout), "DISC\n", 5);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -