Exemplo n.º 1
0
void* client_func(void* p) {
	pthread_mutex_lock(&mutex);
	int* arguments = (int*) p;
	int client_sd = arguments[0];
	busy = FALSE;
	pthread_cond_signal(&thread_ready);
	pthread_mutex_unlock(&mutex);

	struct sockaddr_in client_addr;
	socklen_t addr_len = sizeof(client_addr);
	getpeername(client_sd, (struct sockaddr*) &client_addr, &addr_len);

	printf("s> accept %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

	char bytes[MSG_BUFFER];
	ssize_t bytes_read, bytes_written;
	while(TRUE) {
		if((bytes_read = read(client_sd, bytes, MSG_BUFFER)) == -1) {
			perror("s> Could not receive data from client.\n");
			break;
		} else if(bytes_read == 0) {
			printf("s> %s:%d quit\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
			close(client_sd);
			pthread_exit(EXIT_SUCCESS);
		}

		if(bytes[0] == PUT_CODE) {
      struct put *petition = (struct put *) &bytes;

      // Create file from received data

      // receive size
      char size[10];
      ssize_t bytes_read;
      if((bytes_read = read(client_sd, size, 10)) == -1) {
        perror("c> Error receiving data from client.\n");
        break;
      } else if(bytes_read == 0) {
        printf("c> Client has closed the connection.\n");
        close(client_sd);
        break;
      }                         

      int filesize = atoi(size);
      printf("c> File size - %d\n", filesize);

      //receive actual file data

      char file_data[filesize];
      if((bytes_read = read(client_sd, file_data, filesize)) == -1) {
        perror("c> Error receiving data from client.\n");
        break;
      } else if(bytes_read == 0) {
        printf("c> Client has closed the connection.\n");
        close(client_sd);
        break;
      } 

      //create file
      FILE *file = fopen(petition->src, "wb");
      fwrite(file_data, filesize, 1, file);
      fclose(file);

      // Create graphic
      generate_graphics(petition->title, 
                        petition->xLabel,
                        petition->yLabel,
                        petition->style,
                        petition->src);

      printf("s> %s:%d OK gnuplot %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), petition->title);
   
      // Send ACK to client.
      char byte[1];
      byte[0] = PUT_CODE;
			if((bytes_written = write(client_sd, byte, 1)) == -1) {
				perror("s> Could not send data to client.\n");
				break;
			} 

    } else if (bytes[0] == GET_CODE) {
      struct get *petition = (struct get *) &bytes;
      printf("s> %s:%d init get graphic %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), petition->file);

      //Open file
      FILE *file;
      char *file_data;
      if ((file = fopen(petition->file, "rb")) != 0){
        fseek(file, 0L, SEEK_END);
        int size = ftell(file);
        fseek(file, 0L, SEEK_SET);

        //Allocate memory
        file_data=(char *)malloc(size+1);

        //Read file contents into buffer
        fread(file_data, size, 1, file);
        fclose(file);

        char filesize[10];
        sprintf(filesize, "%d", size);

        // SEND size
        if((bytes_written = send(client_sd, filesize, 10, 0)) == -1) {
          perror("s> Could not send file size to client.\n");
          break;
        }

        //SEND file
        if((bytes_written = sendfile(client_sd, open(petition->file, 0), 0, size)) == -1) {
          perror("s> Could not send data to client.\n");
          break;
        }

        printf("s> %s:%d end get graphic %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), petition->file); 
      } else {
        printf("s> %s:%d error sending file %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), petition->file);  
      }
     
    } 

		memset(bytes, 0, sizeof(bytes));
	}

	close(client_sd);
	pthread_exit(0);
} 
Exemplo n.º 2
0
static int do_sendfile(const int out_fd, const int in_fd,
                       unsigned int num_send, filesize_t start_pos)
{
  /* Probably should one day be shared with instance in ftpdataio.c */
  static char* p_recvbuf;
  unsigned int total_written = 0;
  int retval;
  enum EVSFSysUtilError error;
  (void) start_pos;
  (void) error;
#if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_AIX_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
  if (tunable_use_sendfile)
  {
    static int s_sendfile_checked;
    static int s_runtime_sendfile_works;
    if (!s_sendfile_checked || s_runtime_sendfile_works)
    {
      do
      {
  #ifdef VSF_SYSDEP_HAVE_LINUX_SENDFILE
        retval = sendfile(out_fd, in_fd, NULL, num_send);
  #elif defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE)
        {
          /* XXX - start_pos will truncate on 32-bit machines - can we
           * say "start from current pos"?
           */
          off_t written = 0;
          retval = sendfile(in_fd, out_fd, start_pos, num_send, NULL,
                            &written, 0);
          /* Translate to Linux-like retval */
          if (written > 0)
          {
            retval = (int) written;
          }
        }
  #elif defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
        {
          size_t written = 0;
          struct sendfilevec the_vec;
          vsf_sysutil_memclr(&the_vec, sizeof(the_vec));
          the_vec.sfv_fd = in_fd;
          the_vec.sfv_off = start_pos;
          the_vec.sfv_len = num_send;
          retval = sendfilev(out_fd, &the_vec, 1, &written);
          /* Translate to Linux-like retval */
          if (written > 0)
          {
            retval = (int) written;
          }
        }
  #elif defined(VSF_SYSDEP_HAVE_AIX_SENDFILE)
        {
          struct sf_parms sf_iobuf;
          vsf_sysutil_memclr(&sf_iobuf, sizeof(sf_iobuf));
          sf_iobuf.header_data = NULL;
          sf_iobuf.header_length = 0;
          sf_iobuf.trailer_data = NULL;
          sf_iobuf.trailer_length = 0;
          sf_iobuf.file_descriptor = in_fd;
          sf_iobuf.file_offset = start_pos;
          sf_iobuf.file_bytes = num_send;

          retval = send_file((int*)&out_fd, &sf_iobuf, 0);
          if (retval >= 0)
          {
            retval = sf_iobuf.bytes_sent;
          }
        }
  #else /* must be VSF_SYSDEP_HAVE_HPUX_SENDFILE */
        {
          retval = sendfile(out_fd, in_fd, start_pos, num_send, NULL, 0);
        }
  #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */
        error = vsf_sysutil_get_error();
        vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, out_fd);
      }
      while (vsf_sysutil_retval_is_error(retval) &&
             error == kVSFSysUtilErrINTR);
      if (!s_sendfile_checked)
      {
        s_sendfile_checked = 1;
        if (!vsf_sysutil_retval_is_error(retval) ||
            error != kVSFSysUtilErrNOSYS)
        {
          s_runtime_sendfile_works = 1;
        }
      }
      if (!vsf_sysutil_retval_is_error(retval))
      {
        return retval;
      }
      if (s_runtime_sendfile_works && error != kVSFSysUtilErrINVAL &&
          error != kVSFSysUtilErrOPNOTSUPP)
      {
        return retval;
      }
      /* Fall thru to normal implementation. We won't check again. NOTE -
       * also falls through if sendfile() is OK but it returns EINVAL. For
       * Linux this means the file was not page cache backed. Original
       * complaint was trying to serve files from an NTFS filesystem!
       */
    }
  }
#endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE || VSF_SYSDEP_HAVE_FREEBSD_SENDFILE */
  if (p_recvbuf == 0)
  {
    vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE);
  }
  while (1)
  {
    unsigned int num_read;
    unsigned int num_written;
    unsigned int num_read_this_time = VSFTP_DATA_BUFSIZE;
    if (num_read_this_time > num_send)
    {
      num_read_this_time = num_send;
    }
    retval = vsf_sysutil_read(in_fd, p_recvbuf, num_read_this_time);
    if (retval < 0)
    {
      return retval;
    }
    else if (retval == 0)
    {
      return -1;
    }
    num_read = (unsigned int) retval;
    retval = vsf_sysutil_write_loop(out_fd, p_recvbuf, num_read);
    if (retval < 0)
    {
      return retval;
    }
    num_written = (unsigned int) retval;
    total_written += num_written;
    if (num_written != num_read)
    {
      return num_written;
    }
    if (num_written > num_send)
    {
      bug("num_written bigger than num_send in do_sendfile");
    }
    num_send -= num_written;
    if (num_send == 0)
    {
      /* Bingo! */
      return total_written;
    }
  }
}
Exemplo n.º 3
0
//response static resource
void http_response_static_proc( httpHeader* reqHeader )
{
	int len, cllen , ctlen ;
	char path[1024] = {0};
	header_out_t  header_out;
	memset( &header_out , 0 , sizeof( header_out ));
	header_out.req = reqHeader;

	get_file_path( reqHeader->uri , path );
	struct stat stat_file;
	int ret =  stat( path , &stat_file );

	if ( ret < 0 )
	{
		//printf( "not found page=%s \n" , path );
		resp_error_page( &header_out , 404 );
		return;
	}

	create_common_header( &header_out , 200 );
	header_append_length( &header_out , stat_file.st_size );
	resp_append_header( &header_out , HEADER_END_LINE );

	int nwritten = write( reqHeader->connfd , header_out.data , header_out.length );
	if (nwritten <= 0)
	{
		printf( "I/O error writing to client connfd=%d,len=%d: %s \n", reqHeader->connfd , header_out.length , strerror(errno));
		return;
	}

	int fd = open( path , O_RDONLY );
	if ( fd < 0 )
	{
		printf( "Open file Error:%s,errno=%d \n" , strerror(errno) , errno );
		return;
	}
    //优化
	//setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on));
	off_t offset = 0;
	int force_close = 0;
	while ( offset < stat_file.st_size  )
	{
		int sendn = sendfile( reqHeader->connfd , fd , &offset , stat_file.st_size - offset );
		if ( sendn < 0 )
		{
			//如果socket缓冲区不可用,则挂起等待可用
			if (errno == EAGAIN || errno == EINTR  )
			{
				if( anetHandup(  reqHeader->connfd , 1000 , AE_WRITABLE ) < 0 )
				{
					//如果超时,退出
					printf( "Sendfile anetHandup timeout.......\n" );
					force_close = 1;
					break;
				}
				else
				{
					//否则继续发送
					continue;
				}
			}
			else
			{
				break;
			}
		}
		//printf( "Response uri=%s, connfd=%d,len=%d,send=%d \n", reqHeader->uri , reqHeader->connfd ,stat_file.st_size  , sendn );
	}
	close( fd );
	http_close( reqHeader , force_close );
}
Exemplo n.º 4
0
ret_t
cherokee_socket_sendfile (cherokee_socket_t *socket,
                          int      fd,
                          size_t   size,
                          off_t   *offset,
                          ssize_t *sent)
{
	static cherokee_boolean_t no_sys = false;
#if DARWIN_SENDFILE_API || FREEBSD_SENDFILE_API
	int                       re;
#endif
#if DARWIN_SENDFILE_API
	off_t                     _sent  = size;
#endif

	/* Exit if there is no sendfile() function in the system
	 */
	if (unlikely (no_sys))
		return ret_no_sys;

	/* If there is nothing to send then return now, this may be
	 * needed in some systems (i.e. *BSD) because value 0 may have
	 * special meanings or trigger occasional hidden bugs.
	 */
	if (unlikely (size == 0))
		return ret_ok;

	/* Limit size of data that has to be sent.
	 */
	if (size > MAX_SF_BLK_SIZE2)
		size = MAX_SF_BLK_SIZE;

#if defined(LINUX_BROKEN_SENDFILE_API)
	UNUSED(socket);
	UNUSED(fd);
	UNUSED(offset);
	UNUSED(sent);

	/* Large file support is set but native Linux 2.2 or 2.4 sendfile()
	 * does not support _FILE_OFFSET_BITS 64
	 */
	return ret_no_sys;

#elif defined(LINUX_SENDFILE_API)

	/* Linux sendfile
	 *
	 * ssize_t
	 * sendfile (int out_fd, int in_fd, off_t *offset, size_t *count);
	 *
	 * ssize_t
	 * sendfile64 (int out_fd, int in_fd, off64_t *offset, size_t *count);
	 */
	*sent = sendfile (SOCKET_FD(socket),     /* int     out_fd */
	                  fd,                    /* int     in_fd  */
	                  offset,                /* off_t  *offset */
	                  size);                 /* size_t  count  */

	if (*sent < 0) {
		switch (errno) {
		case EINTR:
		case EAGAIN:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
			return ret_eagain;
		case EINVAL:
			/* maybe sendfile is not supported by this FS (no mmap available),
			 * since more than one FS can be used (ext2, ext3, ntfs, etc.)
			 * we should retry with emulated sendfile (read+write).
			 */
			return ret_no_sys;
		case ENOSYS:
			/* This kernel does not support sendfile at all.
			 */
			no_sys = true;
			return ret_no_sys;
		}

		return ret_error;

	} else if (*sent == 0) {
		/* It isn't an error, but it wrote nothing */
		return ret_error;
	}

#elif DARWIN_SENDFILE_API

	/* MacOS X: BSD-like System Call
	 *
	 * int
	 * sendfile (int fd, int s, off_t offset, off_t *len,
	 *           struct sf_hdtr *hdtr, int flags);
	 */
	re = sendfile (fd,                        /* int             fd     */
	               SOCKET_FD(socket),         /* int             s      */
	               *offset,                   /* off_t           offset */
	               &_sent,                    /* off_t          *len    */
	               NULL,                      /* struct sf_hdtr *hdtr   */
	               0);                        /* int             flags  */

	if (re == -1) {
		switch (errno) {
		case EINTR:
		case EAGAIN:
			/* It might have sent some information
			 */
			if (_sent <= 0)
				return ret_eagain;
			break;
		case ENOSYS:
			no_sys = true;
			return ret_no_sys;
		default:
			return ret_error;
		}

	} else if (_sent == 0) {
		/* It wrote nothing. Most likely the file was
		 * truncated and the fd offset is off-limits.
		 */
		return ret_error;
	}

	*sent = _sent;
	*offset = *offset + _sent;

#elif SOLARIS_SENDFILE_API

	*sent = sendfile (SOCKET_FD(socket),     /* int   out_fd */
	                  fd,                    /* int    in_fd */
	                  offset,                /* off_t   *off */
	                  size);                 /* size_t   len */

	if (*sent < 0) {
		switch (errno) {
		case EINTR:
		case EAGAIN:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
			return ret_eagain;
		case ENOSYS:
			/* This kernel does not support sendfile at all.
			 */
			no_sys = true;
			return ret_no_sys;
		case EAFNOSUPPORT:
			return ret_no_sys;
		}
		return ret_error;

	} else if (*sent == 0) {
		/* It isn't an error, but it wrote nothing */
		return ret_error;
	}

#elif FREEBSD_SENDFILE_API
	struct sf_hdtr hdr;
	struct iovec   hdtrl;

	hdr.headers    = &hdtrl;
	hdr.hdr_cnt    = 1;
	hdr.trailers   = NULL;
	hdr.trl_cnt    = 0;

	hdtrl.iov_base = NULL;
	hdtrl.iov_len  = 0;

	*sent = 0;

	/* FreeBSD sendfile: in_fd and out_fd are reversed
	 *
	 * int
	 * sendfile (int fd, int s, off_t offset, size_t nbytes,
	 *           struct sf_hdtr *hdtr, off_t *sbytes, int flags);
	 */
	re = sendfile (fd,                        /* int             fd     */
	               SOCKET_FD(socket),         /* int             s      */
	               *offset,                   /* off_t           offset */
	               size,                      /* size_t          nbytes */
	               &hdr,                      /* struct sf_hdtr *hdtr   */
	               sent,                      /* off_t          *sbytes */
	               0);                        /* int             flags  */

	if (re == -1) {
		switch (errno) {
		case EINTR:
		case EAGAIN:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
			if (*sent < 1)
				return ret_eagain;

			/* else it's ok, something has been sent.
			 */
			break;
		case ENOSYS:
			no_sys = true;
			return ret_no_sys;
		default:
			return ret_error;
		}

	} else if (*sent == 0) {
		/* It isn't an error, but it wrote nothing */
		return ret_error;
	}

	*offset = *offset + *sent;

#elif HPUX_SENDFILE_API

	/* HP-UX:
	 *
	 * sbsize_t sendfile(int s, int fd, off_t offset, bsize_t nbytes,
	 *                   const struct iovec *hdtrl, int flags);
	 *
	 * HPUX guarantees that if any data was written before
	 * a signal interrupt then sendfile returns the number of
	 * bytes written (which may be less than requested) not -1.
	 * nwritten includes the header data sent.
	 */
	*sent = sendfile (SOCKET_FD(socket),     /* socket          */
	                  fd,                    /* fd to send      */
	                  *offset,               /* where to start  */
	                  size,                  /* bytes to send   */
	                  NULL,                  /* Headers/footers */
	                  0);                    /* flags           */
	if (*sent < 0) {
		switch (errno) {
		case EINTR:
		case EAGAIN:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
		case EWOULDBLOCK:
#endif
			return ret_eagain;
		case ENOSYS:
			no_sys = true;
			return ret_no_sys;
		}
		return ret_error;

	} else if (*sent == 0) {
		/* It isn't an error, but it wrote nothing */
		return ret_error;
	}

	*offset = *offset + *sent;

#else
	UNUSED(socket);
	UNUSED(fd);
	UNUSED(offset);
	UNUSED(sent);

	SHOULDNT_HAPPEN;
	return ret_error;
#endif

	return ret_ok;
}
Exemplo n.º 5
0
static void* cacheopen(char const* url) {
    const char* basename = strrchr(url,'/');
    assert(basename);

    static char dest[508];
    snprintf(dest,508,"%s/%s",cacheDir,basename);

    bool didtemp = false;

    int doopen(void) {
        int result = open(dest,O_RDONLY);
        if(result<0) {
            char temp[512];
            snprintf(temp,512,"%s.temp",dest);

            if(xmlIOHTTPMatch(url)) {
                void* ctx = NULL;
#if W3_ARE_NOT_MORONS
                ctx = xmlNanoHTTPOpen(url, NULL);
                if(xmlNanoHTTPReturnCode(ctx) != 200)
#else
                if(true)
#endif
                {
                    // XXX: it always is... w3.org dies on HTTP/1.0
#if W3_ARE_NOT_MORONS
                    xmlNanoHTTPClose(ctx);
#endif
                    fprintf(stderr,"Curl fallback for %s\n",url);
                    int pid = fork();
                    if(pid == 0) {
                        execlp("curl","curl","-o",temp,url,NULL);
                        abort();
                    }
                    int status = 0;
                    waitpid(pid,&status,0);
                    if(!(WIFEXITED(status) && (0 == WEXITSTATUS(status)))) {
                        fprintf(stderr,"CUrl failed! %x %d\n",status,WEXITSTATUS(status));
                        abort();
                    }
                } else {
                    assert(0==xmlNanoHTTPSave(ctx,temp));
                }
            } else if(xmlIOFTPMatch(url)) {
                void* ftp = xmlNanoFTPOpen(url);
                int out = open(temp,O_WRONLY|O_TRUNC|O_CREAT,0644);
                assert(out>0);
                char buf[0x1000];
                for(;;) {
                    int amt = xmlNanoFTPRead(ftp, buf, 0x1000);
                    if(amt==0) break;
                    assert(amt>0);
                    write(out,buf,amt);
                }
                close(out);            
            } else {
                FILE* fp = xmlFileOpen(url);
                struct stat fpstat;
                if(!fp) {
                    fprintf(stderr,"No idea what to do with url %s\n",url);
                    abort();
                }
                int inp = fileno(fp);
                assert(0==fstat(inp,&fpstat));
                off_t left = fpstat.st_size;
                int out = open(temp,O_WRONLY|O_TRUNC|O_CREAT,0644);
                assert(out>0);
                do {
                    ssize_t amt = sendfile(out,inp,NULL,left);
                    if(amt<0) {
                        perror(url);
                    }
                    assert(amt>=0);
                    left -= amt;
                } while(left > 0);
                fclose(fp);
                close(out);
            }
            rename(temp,dest); // doesn't matter if fails
            unlink(temp); // in case it failed
            return doopen();
        }
        return result;
    }
Exemplo n.º 6
0
ssize_t sendfile_full(int out_fd, const char *fn) {
        _cleanup_fclose_ FILE *f;
        struct stat st;
        int r;
        ssize_t s;

        size_t n, l;
        _cleanup_free_ char *buf = NULL;

        assert(out_fd > 0);
        assert(fn);

        f = fopen(fn, "re");
        if (!f)
                return -errno;

        r = fstat(fileno(f), &st);
        if (r < 0)
                return -errno;

        s = sendfile(out_fd, fileno(f), NULL, st.st_size);
        if (s < 0)
                if (errno == EINVAL || errno == ENOSYS) {
                        /* continue below */
                } else
                        return -errno;
        else
                return s;

        /* sendfile() failed, fall back to read/write */

        /* Safety check */
        if (st.st_size > 4*1024*1024)
                return -E2BIG;

        n = st.st_size > 0 ? st.st_size : LINE_MAX;
        l = 0;

        while (true) {
                char *t;
                size_t k;

                t = realloc(buf, n);
                if (!t)
                        return -ENOMEM;

                buf = t;
                k = fread(buf + l, 1, n - l, f);

                if (k <= 0) {
                        if (ferror(f))
                                return -errno;

                        break;
                }

                l += k;
                n *= 2;

                /* Safety check */
                if (n > 4*1024*1024)
                        return -E2BIG;
        }

        r = write(out_fd, buf, l);
        if (r < 0)
                return -errno;

        return (ssize_t) l;
}
Exemplo n.º 7
0
bool
client_test(int argc, char **argv)
{
    FILE *out = NULL;
    FILE *err = NULL;

    char *ack = NULL;

    const char *filename = NULL;
    const char *host = NULL;
    const char *port = NULL;
    off_t offset = 0;

    bool check = false;

    int sockfd,
        tmperr,
        write_count,
        fdin,
        size,
        wait_for_ack,
        req,
        next_opt;

    const char *short_opt = "no:";
    const struct option long_opt[] = {
        {"no-ack", 0, NULL, 'n'},
        {"output", 1, NULL, 'o'},
        {NULL,     0, NULL, 0},
    };

    /* Just in case we want to redirect stderr later on. */
    err = stderr;
    out = stdout;
    wait_for_ack = 1;

    do
    {
        next_opt = getopt_long(argc, argv, short_opt, long_opt, NULL);
        switch(next_opt)
        {

        case 'o':       /* -o or --output ... optional */
            out = redirect(optarg, "a", stdout);
            break;

        case 'n':       /* -n or --no-ack ... optional */
            wait_for_ack = 0;
            break;

        case '?':       /* invalid option */
            usage(err, EXIT_FAILURE);
            break;

        /* End of options */
        case -1:
            break;

        /* If we get here, something went very wrong. */
        default:
            abort();
            break;

        }
    } while(next_opt != -1);


    argv += optind;
    argc -= optind;

    if(argc != 3)
        usage(err, EXIT_FAILURE);

    host = argv[0];
    port = argv[1];
    filename = argv[2];

    if(filename == NULL)
        die(err, EINVAL,
            "%s: HL7 filename required.\n", program);

    if(host == NULL)
        die(err, EDESTADDRREQ,
            "%s: Destination host required.\n", program);

    if(port == NULL)
        die(err, EINVAL,
            "%s: Destination port required.\n", program);


    fdin = sockfd = -1;
    write_count = 0;

    size = getsize(filename);

    /* Save errno, as writing to a stream can change it in the
     * interim.
     */

    tmperr = errno;

    if(size <= 0)
    {
        switch(size)
        {
        case 0:
            die(err, EXIT_FAILURE,
                "%s: %s: Cowardly refusing to send an empty file!\n",
                program, filename);
            break;

        case -1:
            die(err, tmperr,
                "%s: Could not open \"%s\": %s\n",
                program, filename, strerror(errno));
            break;

        default:
            die(err, EXIT_FAILURE,
                "%s: Could not open \"%s\"\n",
                program, filename);
            break;
        }
    }

    if(!tcp_connect(host, atoi(port), &sockfd))
    {
        tmperr = errno;
        switch(sockfd)
        {
        case -1:
            die(err, EXIT_FAILURE,
                "Error opening socket.\n");
            break;

        case -2:
            die(err, EXIT_FAILURE,
                "%s: Hostname lookup failure: %s\n",
                program, host);
            break;

        case -3:
            die(err, tmperr,
                "%s: error connecting to %s, port %s.\n",
                program, host, port);
            break;

        default:    /* If we get here, the API is busted. */
            die(err, EXIT_FAILURE,
                "%s: Unknown error!\n", program);
            break;

        }
    }

    /* Read file and send to server */

    if((fdin = open(filename, O_RDONLY)) == -1)
    {
        die(err, errno,
            "%s: couldn't open %s for reading: %s\n",
            program, filename, strerror(errno));
    }
    else
    {
        /* Toss file to server. Linux syscall, but its fast. :D*/
        sendfile(sockfd, fdin, &offset, size);

        if(wait_for_ack)
        {
            ack = tcp_recv(sockfd, 5000, MAX_READ, &req);
            if(ack==NULL)
                return false;

            if((ack!=NULL) &&
                    (strlen(ack) > 0))
            {
                fprintf(stderr, "%s\n", ack);
                check = parse(ack);
            }
            free(ack);
            ack = NULL;
            close(sockfd);

            return check;
        } /* if waiting for ack ... */
        close(sockfd);
    } /* if able to open filestream... */
    return true;
}
Exemplo n.º 8
0
void do_sendfile(OFF_T offset, int i)
{
	int in_fd;
	struct stat sb;
	int wait_status;
	int wait_stat;
	off_t before_pos, after_pos;

	out_fd = create_server();

	if ((in_fd = open(in_file, O_RDONLY)) < 0) {
		tst_brkm(TBROK, cleanup, "open failed: %d", errno);
	 /*NOTREACHED*/}
	if (stat(in_file, &sb) < 0) {
		tst_brkm(TBROK, cleanup, "stat failed: %d", errno);
	 /*NOTREACHED*/}

	if ((before_pos = lseek(in_fd, 0, SEEK_CUR)) < 0) {
		tst_brkm(TBROK, cleanup,
			 "lseek before invoking sendfile failed: %d", errno);
	 /*NOTREACHED*/}

	TEST(sendfile(out_fd, in_fd, &offset, sb.st_size - offset));

	if ((after_pos = lseek(in_fd, 0, SEEK_CUR)) < 0) {
		tst_brkm(TBROK, cleanup,
			 "lseek after invoking sendfile failed: %d", errno);
	 /*NOTREACHED*/}

	if (STD_FUNCTIONAL_TEST) {
		/* Close the sockets */
		shutdown(sockfd, SHUT_RDWR);
		shutdown(s, SHUT_RDWR);
		if (TEST_RETURN != testcases[i].exp_retval) {
			tst_resm(TFAIL, "sendfile(2) failed to return "
				 "expected value, expected: %d, "
				 "got: %ld", testcases[i].exp_retval,
				 TEST_RETURN);
			kill(child_pid, SIGKILL);
		} else if (offset != testcases[i].exp_updated_offset) {
			tst_resm(TFAIL, "sendfile(2) failed to update "
				 "OFFSET parameter to expected value, "
				 "expected: %d, got: %"PRId64,
				 testcases[i].exp_updated_offset, (int64_t)offset);
		} else if (before_pos != after_pos) {
			tst_resm(TFAIL, "sendfile(2) updated the file position "
				 " of in_fd unexpectedly, expected file position: %"PRId64", "
				 " actual file position %"PRId64,
				 (int64_t)before_pos, (int64_t)after_pos);
		} else {
			tst_resm(TPASS, "functionality of sendfile() is "
				 "correct");
			wait_status = waitpid(-1, &wait_stat, 0);
		}
	} else {
		tst_resm(TPASS, "call succeeded");
		/* Close the sockets */
		shutdown(sockfd, SHUT_RDWR);
		shutdown(s, SHUT_RDWR);
		if (TEST_RETURN != testcases[i].exp_retval) {
			kill(child_pid, SIGKILL);
		} else {
			wait_status = waitpid(-1, &wait_stat, 0);
		}
	}

	close(in_fd);

}
int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq, off_t max_bytes) {
	chunk *c;

	for(c = cq->first; (max_bytes > 0) && (NULL != c); c = c->next) {
		int chunk_finished = 0;

		switch(c->type) {
		case MEM_CHUNK: {
			char * offset;
			off_t toSend;
			ssize_t r;

			size_t num_chunks, i;
			struct iovec chunks[UIO_MAXIOV];
			chunk *tc;
			size_t num_bytes = 0;

			/* build writev list
			 *
			 * 1. limit: num_chunks < UIO_MAXIOV
			 * 2. limit: num_bytes < max_bytes
			 */
			for (num_chunks = 0, tc = c;
			     tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
			     tc = tc->next, num_chunks++);

			for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
				if (buffer_string_is_empty(tc->mem)) {
					chunks[i].iov_base = tc->mem->ptr;
					chunks[i].iov_len  = 0;
				} else {
					offset = tc->mem->ptr + tc->offset;
					toSend = buffer_string_length(tc->mem) - tc->offset;

					chunks[i].iov_base = offset;

					/* protect the return value of writev() */
					if (toSend > max_bytes ||
					    (off_t) num_bytes + toSend > max_bytes) {
						chunks[i].iov_len = max_bytes - num_bytes;

						num_chunks = i + 1;
						break;
					} else {
						chunks[i].iov_len = toSend;
					}

					num_bytes += toSend;
				}
			}

			if ((r = writev(fd, chunks, num_chunks)) < 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
							"writev failed:", strerror(errno), fd);

					return -1;
				}
			}

			/* check which chunks have been written */
			cq->bytes_out += r;
			max_bytes -= r;

			for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
				if (r >= (ssize_t)chunks[i].iov_len) {
					/* written */
					r -= chunks[i].iov_len;
					tc->offset += chunks[i].iov_len;

					if (chunk_finished) {
						/* skip the chunks from further touches */
						c = c->next;
					} else {
						/* chunks_written + c = c->next is done in the for()*/
						chunk_finished = 1;
					}
				} else {
					/* partially written */

					tc->offset += r;
					chunk_finished = 0;

					break;
				}
			}

			break;
		}
		case FILE_CHUNK: {
			ssize_t r;
			off_t offset;
			off_t toSend;
			stat_cache_entry *sce = NULL;

			offset = c->file.start + c->offset;
			toSend = c->file.length - c->offset;
			if (toSend > max_bytes) toSend = max_bytes;

			/* open file if not already opened */
			if (-1 == c->file.fd) {
				if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
					log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));

					return -1;
				}
				fd_close_on_exec(c->file.fd);
#ifdef HAVE_POSIX_FADVISE
				/* tell the kernel that we want to stream the file */
				if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
					if (ENOSYS != errno) {
						log_error_write(srv, __FILE__, __LINE__, "ssd",
							"posix_fadvise failed:", strerror(errno), c->file.fd);
					}
				}
#endif
			}

			if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					/* ok, we can't send more, let's try later again */
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
							"sendfile failed:", strerror(errno), fd);
					return -1;
				}
			} else if (r == 0) {
				int oerrno = errno;
				/* We got an event to write but we wrote nothing
				 *
				 * - the file shrinked -> error
				 * - the remote side closed inbetween -> remote-close */

				if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
					/* file is gone ? */
					return -1;
				}

				if (offset > sce->st.st_size) {
					/* file shrinked, close the connection */
					errno = oerrno;

					return -1;
				}

				errno = oerrno;
				return -2;
			}

#ifdef HAVE_POSIX_FADVISE
#if 0
#define K * 1024
#define M * 1024 K
#define READ_AHEAD 4 M
			/* check if we need a new chunk */
			if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
				/* tell the kernel that we want to stream the file */
				if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"posix_fadvise failed:", strerror(errno), c->file.fd);
				}
			}
#endif
#endif

			c->offset += r;
			cq->bytes_out += r;
			max_bytes -= r;

			if (c->offset == c->file.length) {
				chunk_finished = 1;

				/* chunk_free() / chunk_reset() will cleanup for us but it is a ok to be faster :) */

				if (c->file.fd != -1) {
					close(c->file.fd);
					c->file.fd = -1;
				}
			}

			break;
		}
		default:

			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");

			return -1;
		}

		if (!chunk_finished) {
			/* not finished yet */

			break;
		}
	}

	return 0;
}
Exemplo n.º 10
0
 ssize_t portable_sendfile(int out_fd, int in_fd) {
   off_t len = SENDFILE_CHUNK_SIZE;
   if(sendfile(in_fd, out_fd, 0, &len, NULL, 0) == -1)
     return -1;
   return len;
 }
Exemplo n.º 11
0
 ssize_t portable_sendfile(int out_fd, int in_fd) {
   return sendfile(out_fd, in_fd, NULL, SENDFILE_CHUNK_SIZE);
 }
Exemplo n.º 12
0
int main(int argc, char *argv[]){

	int listenfd,connfd,n;
	int epoll_fd,cur_fd,newfd,number,stop;
	struct epoll_event ev;
	struct epoll_event events[size];
	struct sockaddr_in server_address,client_address;
	struct stat stat_buf;
	const char* file_name=argv[1];
	char buffer[BUF];

	int file_ptr=open(file_name,O_RDONLY);
	fstat(file_ptr,&stat_buf);
	close(file_ptr);
	bzero(&server_address,sizeof(server_address));
	server_address.sin_family=AF_INET;
	server_address.sin_addr.s_addr=htonl(INADDR_ANY);
	server_address.sin_port=htons(PORT);

	if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1){
		exit(0);
	}
	setnonblocking(listenfd);
	int opt=1;
	setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	if(bind(listenfd,(struct sockaddr*)&server_address,sizeof(server_address))==-1){
		exit(0);
	}
	if(listen(listenfd,BACKLOG)==-1){
		exit(0);
	}

	epoll_fd=epoll_create(10);
	ev.data.fd=listenfd;
	ev.events=EPOLLIN | EPOLLET;
	epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listenfd,&ev);

	cur_fd=1;stop=FALSE;
	socklen_t len=sizeof(struct sockaddr_in);

	while(!stop){
		number=epoll_wait(epoll_fd,events,cur_fd,-1);
		assert(number!=-1);
		for(n=0;n<number;n++){

			connfd=events[n].data.fd;

			if(connfd==listenfd){

				while((newfd=accept(listenfd,(struct sockaddr*)&client_address,&len))>0){
					printf("connect with %s ,socket index %d\n",\
								inet_ntoa(client_address.sin_addr),newfd);
					setnonblocking(newfd);
					ev.data.fd=newfd;
					ev.events=EPOLLIN|EPOLLET|EPOLLHUP;
					if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,newfd,&ev)==-1){
						perror("epoll_ctl:add");
						stop=TRUE;
					}
					cur_fd++;
				}

				if(newfd==-1){
					if(errno!=EAGAIN&&errno!=ECONNABORTED\
								&&errno!=EPROTO&&errno!=EINTR){
						perror("accept");
					}
				}

				continue;

			}else if(events[n].events & EPOLLOUT){

				printf("start to sendfile !\n");
				int ret=0,left=stat_buf.st_size;
				file_ptr=open(file_name,O_RDONLY);

				while(left>0){
					ret=sendfile(connfd,file_ptr,NULL,BUF);
					if(ret<0 && errno==EAGAIN){
						continue;
					}else if(ret==0){
						break;
					}else{
						left-=ret;
					}
				}

				printf("sendfile over !\n");
				close(file_ptr);

				ev.data.fd=connfd;
				epoll_ctl(epoll_fd,EPOLL_CTL_DEL,connfd,&ev);

				cur_fd--;
				close(connfd);

			}else if(events[n].events & EPOLLIN){

				char msg[100];
				memset(msg,'\0',100);
				int ret=recv(connfd,msg,100,0);
				if(ret<=0){
					close(connfd);
				}

				printf("recv from client : %s\n",msg);

				ev.data.fd=connfd;
				ev.events=EPOLLOUT|EPOLLET|EPOLLHUP;
				epoll_ctl(epoll_fd,EPOLL_CTL_MOD,connfd,&ev);

			}
		}

	}
	close(listenfd);
	close(epoll_fd);
	return 0;

}
Exemplo n.º 13
0
static int 
spamdscan_socket(const char *file, const struct spamd_server *srv, struct config_file *cfg, rspamd_result_t *res)
{
#ifdef HAVE_PATH_MAX
	char buf[PATH_MAX + 10];
#elif defined(HAVE_MAXPATHLEN)
	char buf[MAXPATHLEN + 10];
#else
#error "neither PATH_MAX nor MAXPATHEN defined"
#endif
	char *c, *err;
	struct sockaddr_un server_un;
	struct sockaddr_in server_in;
	int s, r, fd, ofl, size = 0;
	struct stat sb;
	struct rspamd_metric_result *cur = NULL;
	struct rspamd_symbol *cur_symbol;

	/* somebody doesn't need reply... */
	if (!srv)
		return 0;

	if (srv->sock_type == AF_LOCAL) {

		memset(&server_un, 0, sizeof(server_un));
		server_un.sun_family = AF_UNIX;
		strncpy(server_un.sun_path, srv->sock.unix_path, sizeof(server_un.sun_path));

		if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
			msg_warn("spamd: socket %s, %s", srv->sock.unix_path,
					strerror (errno));
			return -1;
		}
		if (connect_t(s, (struct sockaddr *) & server_un, sizeof(server_un), cfg->spamd_connect_timeout) < 0) {
			msg_warn("spamd: connect %s, %s", srv->sock.unix_path,
					strerror (errno));
			close(s);
			return -1;
		}
	} else {
		/* inet hostname, send stream over tcp/ip */

		memset(&server_in, 0, sizeof(server_in));
		server_in.sin_family = AF_INET;
		server_in.sin_port = srv->sock.inet.port;
		memcpy((char *)&server_in.sin_addr, &srv->sock.inet.addr, sizeof(struct in_addr));

		if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
			msg_warn("spamd: socket %s", strerror (errno));
			return -1;
		}
		if (connect_t(s, (struct sockaddr *) & server_in, sizeof(server_in), cfg->spamd_connect_timeout) < 0) {
			msg_warn("spamd: connect %s, %s", srv->name, strerror (errno));
			close(s);
			return -1;
		}
	}
	/* Get file size */
	fd = open(file, O_RDONLY);
	if (fstat (fd, &sb) == -1) {
		msg_warn ("spamd: stat failed: %s", strerror (errno));
		close(s);
		return -1;
	}
	
	if (poll_fd(s, cfg->spamd_connect_timeout, POLLOUT) < 1) {
		msg_warn ("spamd: timeout waiting writing, %s", srv->name);
		close (s);
		return -1;
	}
	/* Set blocking again */
	ofl = fcntl(s, F_GETFL, 0);
	fcntl(s, F_SETFL, ofl & (~O_NONBLOCK));

	r = snprintf (buf, sizeof (buf), "SYMBOLS SPAMC/1.2\r\nContent-length: %ld\r\n\r\n", (long int)sb.st_size);
	if (write (s, buf, r) == -1) {
		msg_warn("spamd: write (%s), %s", srv->name, strerror (errno));
		close(fd);
		close(s);
		return -1;
	}

#ifdef HAVE_SENDFILE
#if defined(FREEBSD)
	if (sendfile(fd, s, 0, 0, 0, 0, 0) != 0) {
		msg_warn("spamd: sendfile (%s), %s", srv->name, strerror (errno));
		close(fd);
		close(s);
		return -1;
	}
#elif defined(LINUX)
	off_t off = 0;
	if (sendfile(s, fd, &off, sb.st_size) == -1) {
		msg_warn("spamd: sendfile (%s), %s", srv->name, strerror (errno));
		close(fd);
		close(s);
		return -1;		
	}
#endif
#else 
	while ((r = read (fd, buf, sizeof (buf))) > 0) {
		write (s, buf, r);
	}
#endif

	fcntl(s, F_SETFL, ofl);
	close(fd);

	/* wait for reply */

	if (poll_fd(s, cfg->spamd_results_timeout, POLLIN) < 1) {
		msg_warn("spamd: timeout waiting results %s", srv->name);
		close(s);
		return -1;
	}
	
	/*
	 * read results
	 */

	buf[0] = 0;

	while ((r = read(s, buf + size, sizeof (buf) - size - 1)) > 0 && size < sizeof (buf) - 1) {
		size += r;
	}
	buf[size] = 0;

	if (r < 0) {
		msg_warn("spamd: read, %s, %s", srv->name, strerror (errno));
		close(s);
		return -1;
	}

	close(s);

	/*
	 * ok, we got result; test what we got
	 */

	if ((c = strstr(buf, "Spam: ")) == NULL) {
		msg_warn("spamd: unexpected result on file (%s) %s, %s", srv->name, file, buf);
		return -2;
	}
	else {

		cur = malloc (sizeof (struct rspamd_metric_result));
		if (cur == NULL) {
			msg_err ("malloc falied: %s", strerror (errno));
			return -1;
		}
		bzero (cur, sizeof (struct rspamd_metric_result));
		/* Find mark */
		c = strchr (c, ';');
		if (c != NULL && *c != '\0') {
			cur->score = strtod (c + 1, &err);
			if (*err == ' ' && *(err + 1) == '/') {
				cur->required_score = strtod (err + 3, NULL);
			}
			else {
				cur->score = 0;
			}
		}
		else {
			cur->score = 0;
			cur->required_score = 0;
		}
	}

	/* Skip empty lines */
	while (*c && *c++ != '\n');
	while (*c++ && (*c == '\r' || *c == '\n'));
	/* Write symbols */
	if (*c != '\0') {
		err = strchr (c, '\r');
		if (err != NULL) {
			*err = '\0';
		}
		cur_symbol = malloc (sizeof (struct rspamd_symbol));
		cur_symbol->symbol = strdup (c);
		TAILQ_INSERT_HEAD(&cur->symbols, cur_symbol, entry);
	}

	if (strstr(buf, "True") != NULL) {
		cur->action = METRIC_ACTION_REJECT;
		return 1;
	}

	return 0;
}
Exemplo n.º 14
0
static int 
rspamdscan_socket(SMFICTX *ctx, struct mlfi_priv *priv, const struct spamd_server *srv,
		struct config_file *cfg, rspamd_result_t *res, char **mid)
{
	char buf[16384];
	char *c, *p, *err_str;
	struct sockaddr_un server_un;
	struct sockaddr_in server_in;
	int s, r, fd, ofl, size = 0, to_write, written, state, next_state, toklen;
	int remain;
	struct stat sb;
	struct rspamd_metric_result *cur = NULL;
	struct rcpt *rcpt;
	struct rspamd_symbol *cur_symbol;

	/* somebody doesn't need reply... */
	if (!srv)
		return 0;

	if (srv->sock_type == AF_LOCAL) {

		memset(&server_un, 0, sizeof(server_un));
		server_un.sun_family = AF_UNIX;
		strncpy(server_un.sun_path, srv->sock.unix_path, sizeof(server_un.sun_path));

		if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
			msg_warn("rspamd: socket %s, %s", srv->sock.unix_path,
					strerror (errno));
			return -1;
		}
		if (connect_t(s, (struct sockaddr *) & server_un, sizeof(server_un), cfg->spamd_connect_timeout) < 0) {
			msg_warn("rspamd: connect %s, %s", srv->sock.unix_path,
					strerror (errno));
			close(s);
			return -1;
		}
	} else {
		/* inet hostname, send stream over tcp/ip */

		memset(&server_in, 0, sizeof(server_in));
		server_in.sin_family = AF_INET;
		server_in.sin_port = srv->sock.inet.port;
		memcpy((char *)&server_in.sin_addr, &srv->sock.inet.addr, sizeof(struct in_addr));

		if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
			msg_warn("rspamd: socket %s", strerror (errno));
			return -1;
		}
		if (connect_t(s, (struct sockaddr *) & server_in, sizeof(server_in), cfg->spamd_connect_timeout) < 0) {
			msg_warn("rspamd: connect %s: %s", srv->name, strerror (errno));
			close(s);
			return -1;
		}
	}
	/* Get file size */
	fd = open(priv->file, O_RDONLY);
	if (fstat (fd, &sb) == -1) {
		msg_warn ("rspamd: stat failed: %s", strerror (errno));
		close(s);
		return -1;
	}
	
	if (poll_fd(s, cfg->spamd_connect_timeout, POLLOUT) < 1) {
		msg_warn ("rspamd: timeout waiting writing, %s", srv->name);
		close (s);
		return -1;
	}
	/* Set blocking again */
	ofl = fcntl(s, F_GETFL, 0);
	fcntl(s, F_SETFL, ofl & (~O_NONBLOCK));
	
	r = 0;
	to_write = sizeof (buf) - r;
	written = snprintf (buf + r, to_write, "SYMBOLS RSPAMC/1.2\r\nContent-length: %ld\r\n", (long int)sb.st_size);
	if (written > to_write) {
		msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
		close(fd);
		close(s);
		return -1;
	}
	r += written;

	for (rcpt = priv->rcpts.lh_first; rcpt != NULL; rcpt = rcpt->r_list.le_next) {
		to_write = sizeof (buf) - r;
		written = snprintf (buf + r, to_write, "Rcpt: %s\r\n", rcpt->r_addr);
		if (written > to_write) {
			msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
			close(fd);
			close(s);
			return -1;
		}
		r += written;
	}

	if (priv->priv_from[0] != '\0') {
		to_write = sizeof (buf) - r;
		written = snprintf (buf + r, to_write, "From: %s\r\n", priv->priv_from);
		if (written > to_write) {
			msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
			close(fd);
			close(s);
			return -1;
		}
		r += written;
	}
	if (priv->priv_helo[0] != '\0') {
		to_write = sizeof (buf) - r;
		written = snprintf (buf + r, to_write, "Helo: %s\r\n", priv->priv_helo);
		if (written > to_write) {
			msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
			close(fd);
			close(s);
			return -1;
		}
		r += written;
	}
	if (priv->priv_hostname[0] != '\0' && memcmp (priv->priv_hostname, "unknown", 8) != 0) {
		to_write = sizeof (buf) - r;
		written = snprintf (buf + r, to_write, "Hostname: %s\r\n", priv->priv_hostname);
		if (written > to_write) {
			msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
			close(fd);
			close(s);
			return -1;
		}
		r += written;
	}
	if (priv->priv_ip[0] != '\0') {
		to_write = sizeof (buf) - r;
		written = snprintf (buf + r, to_write, "IP: %s\r\n", priv->priv_ip);
		if (written > to_write) {
			msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
			close(fd);
			close(s);
			return -1;
		}
		r += written;
	}
	if (priv->priv_user[0] != '\0') {
		to_write = sizeof (buf) - r;
		written = snprintf (buf + r, to_write, "User: %s\r\n", priv->priv_user);
		if (written > to_write) {
			msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
			close(fd);
			close(s);
			return -1;
		}
		r += written;
	}
	to_write = sizeof (buf) - r;
	written = snprintf (buf + r, to_write, "Queue-ID: %s\r\n\r\n", priv->mlfi_id);
	if (written > to_write) {
		msg_warn("rspamd: buffer overflow while filling buffer (%s)", srv->name);
		close(fd);
		close(s);
		return -1;
	}
	r += written;



	if (write (s, buf, r) == -1) {
		msg_warn("rspamd: write (%s), %s", srv->name, strerror (errno));
		close(fd);
		close(s);
		return -1;
	}

#ifdef HAVE_SENDFILE
#if defined(FREEBSD)
	if (sendfile(fd, s, 0, 0, 0, 0, 0) != 0) {
		msg_warn("rspamd: sendfile (%s), %s", srv->name, strerror (errno));
		close(fd);
		close(s);
		return -1;
	}
#elif defined(LINUX)
	off_t off = 0;
	if (sendfile(s, fd, &off, sb.st_size) == -1) {
		msg_warn("rspamd: sendfile (%s), %s", srv->name, strerror (errno));
		close(fd);
		close(s);
		return -1;		
	}
#endif
#else 
	while ((r = read (fd, buf, sizeof (buf))) > 0) {
		write (s, buf, r);
	}
#endif

	fcntl(s, F_SETFL, ofl);
	close(fd);

	/* wait for reply */

	if (poll_fd(s, cfg->spamd_results_timeout, POLLIN) < 1) {
		msg_warn("rspamd: timeout waiting results %s", srv->name);
		close(s);
		return -1;
	}
	
	/*
	 * read results
	 */

	buf[0] = 0;
	size = 0;
	
	/* XXX: in fact here should be some FSM to parse reply and this one just skip long replies */
	while ((r = read(s, buf + size, sizeof (buf) - size - 1)) > 0 && size < sizeof (buf) - 1) {
		size += r;
	}

	if (r < 0) {
		msg_warn("rspamd: read, %s, %s", srv->name, strerror (errno));
		close(s);
		return -1;
	}
	buf[size] = '\0';
	close(s);

#define TEST_WORD(x)																\
do {																				\
	if (remain < sizeof ((x)) - 1 || memcmp (p, (x), sizeof ((x)) - 1) != 0) {		\
		msg_warn ("invalid reply from server %s at state %d, expected: %s, got %*s", srv->name, state, ((x)), (int)sizeof((x)), p);				\
		return -1;																	\
	}																				\
	p += sizeof((x)) - 1;															\
	remain -= sizeof((x)) - 1;														\
} while (0)


	c = buf;
	p = buf;
	remain = size - 1;
	state = 0;
	next_state = 100;

	while (remain > 0) {
		switch (state) {
			case 0:
				/*
				 * Expect first reply line:
				 * RSPAMD/{VERSION} {ERROR_CODE} {DESCR} CRLF
				 */
				TEST_WORD("RSPAMD/");
				if ((c = strchr (p, ' ')) == NULL) {
					msg_warn ("invalid reply from server %s on state %d", srv->name, state);
					return -1;
				}
				/* Well now in c we have space symbol, skip all */
				while (remain > 0 && isspace (*c)) {
					c ++;
				}
				/* Now check code */
				if (*c != '0') {
					msg_warn ("invalid reply from server %s on state %d, code: %c", srv->name, state, *c);
					return -1;
				}
				/* Now skip everything till \n */
				if ((c = strchr (c, '\n')) == NULL) {
					msg_warn ("invalid reply from server %s on state %d", srv->name, state);
					return -1;
				}
				c ++;
				remain -= c - p;
				p = c;
				next_state = 2;
				state = 99;
				break;
			case 2:
				/*
				 * In this state we compare begin of line with Metric:
				 */
				TEST_WORD("Metric:");
				cur = malloc (sizeof (struct rspamd_metric_result));
				if (cur == NULL) {
					msg_err ("malloc failed: %s", strerror (errno));
					return -1;
				}
				cur->subject = NULL;
				TAILQ_INIT(&cur->symbols);
				next_state = 3;
				state = 99;
				break;
			case 3:
				/* 
				 * In this state we parse metric line 
				 * Typical line looks as name; result; score1 / score2[ / score3] and we are interested in:
				 * name, result, score1 and score2
				 */
				if ((c = strchr (p, ';')) == NULL) {
					msg_warn ("invalid reply from server %s on state %d, at position: %s", srv->name, state, p);
					return -1;
				}
				/* Now in c we have end of name and in p - begin of name, so copy this data to temp buffer */
				cur->metric_name = malloc (c - p + 1);
				if (cur->metric_name == NULL) {
					msg_err ("malloc failed: %s", strerror (errno));
					return -1;
				}
				rmilter_strlcpy (cur->metric_name, p, c - p + 1);
				remain -= c - p + 1;
				p = c + 1;
				/* Now skip result from rspamd, just extract 2 numbers */
				if ((c = strchr (p, ';')) == NULL) {
					msg_warn ("invalid reply from server %s on state %d, at position: %s", srv->name, state, p);
					return -1;
				}
				remain -= c - p + 1;
				p = c + 1;
				/* Now skip spaces */
				while (isspace (*p) && remain > 0) {
					p ++;
					remain --;
				}
				/* Try to read first mark */
				cur->score = strtod (p, &err_str);
				if (err_str != NULL && (*err_str != ' ' && *err_str != '/')) {
					msg_warn ("invalid reply from server %s on state %d, error converting score number: %s", srv->name, state, err_str);
					return -1;
				}
				remain -= err_str - p;
				p = err_str;
				while (remain > 0 && (*p == ' ' || *p == '/')) {
					remain --;
					p ++;
				}
				/* Try to read second mark */
				cur->required_score = strtod (p, &err_str);
				if (err_str != NULL && (*err_str != ' ' && *err_str != '/' && *err_str != '\r')) {
					msg_warn ("invalid reply from server %s on state %d, error converting required score number: %s", srv->name, state, err_str);
					return -1;
				}
				remain -= err_str - p;
				p = err_str;
				while (remain > 0 && *p != '\n') {
					remain --;
					p ++;
				}
				state = 99;
				next_state = 4;
				break;
			case 4:
				/* Symbol/Action */
				if (remain >= sizeof ("Symbol:") && memcmp (p, "Symbol:", sizeof ("Symbol:") - 1) == 0) {
					state = 99;
					next_state = 5;
					p += sizeof("Symbol:") - 1;															\
					remain -= sizeof("Symbol:") - 1;
				}
				else if (remain >= sizeof ("Action:") && memcmp (p, "Action:", sizeof ("Action:") - 1) == 0) {
					state = 99;
					next_state = 6;
					p += sizeof("Action:") - 1;															\
					remain -= sizeof("Action:") - 1;
				}
				else if (remain >= sizeof ("Metric:") && memcmp (p, "Metric:", sizeof ("Metric:") - 1) == 0) {
					state = 99;
					next_state = 3;
					p += sizeof("Metric:") - 1;															\
					remain -= sizeof("Metric:") - 1;
					TAILQ_INSERT_HEAD(res, cur, entry);
					cur = malloc (sizeof (struct rspamd_metric_result));
					if (cur == NULL) {
						msg_err ("malloc failed: %s", strerror (errno));
						return -1;
					}
					TAILQ_INIT(&cur->symbols);
				}
				else if (remain >= sizeof ("Message-ID:") && memcmp (p, "Message-ID:", sizeof ("Message-ID:") - 1) == 0) {
					state = 99;
					next_state = 7;
					p += sizeof("Message-ID:") - 1;															\
					remain -= sizeof("Message-ID:") - 1;
				}
				else if (remain >= sizeof ("Subject:") && memcmp (p, "Subject:", sizeof ("Subject:") - 1) == 0) {
					state = 99;
					next_state = 8;
					p += sizeof("Subject:") - 1;															\
					remain -= sizeof("Subject:") - 1;
				}
				else {
					toklen = strcspn (p, "\r\n");
					if (toklen > remain) {
						msg_info ("bad symbol name detected");
						return -1;
					}
					remain -= toklen;
					p += toklen;
					next_state = 4;
					state = 99;
				}
				break;
			case 5:
				/* Parse symbol line */
				toklen = strcspn (p, ";\r\n");
				if (toklen == 0 || toklen > remain) {
					/* Bad symbol name */
					msg_info ("bad symbol name detected");
					return -1;
				}
				cur_symbol = malloc (sizeof (struct rspamd_symbol));
				if (cur_symbol == NULL) {
					msg_err ("malloc failed: %s", strerror (errno));
					return -1;
				}
				cur_symbol->symbol = malloc (toklen + 1);
				if (cur_symbol->symbol == NULL) {
					msg_err ("malloc failed: %s", strerror (errno));
					return -1;
				}
				rmilter_strlcpy (cur_symbol->symbol, p, toklen + 1);
				TAILQ_INSERT_HEAD (&cur->symbols, cur_symbol, entry);
				/* Skip to the end of line */
				toklen = strcspn (p, "\r\n");
				if (toklen > remain) {
					msg_info ("bad symbol name detected");
					return -1;
				}
				remain -= toklen;
				p += toklen;
				next_state = 4;
				state = 99;
				break;
			case 6:
				/* Parse action */
				if (memcmp (p, "reject", sizeof ("reject") - 1) == 0) {
					cur->action = METRIC_ACTION_REJECT;
				}
				else if (memcmp (p, "greylist", sizeof ("greylist") - 1) == 0) {
					cur->action = METRIC_ACTION_GREYLIST;
				}
				else if (memcmp (p, "add header", sizeof ("add header") - 1) == 0) {
					cur->action = METRIC_ACTION_ADD_HEADER;
				}
				else if (memcmp (p, "rewrite subject", sizeof ("rewrite subject") - 1) == 0) {
					cur->action = METRIC_ACTION_REWRITE_SUBJECT;
				}
				else {
					cur->action = METRIC_ACTION_NOACTION;
				}
				/* Skip to the end of line */
				toklen = strcspn (p, "\r\n");
				if (toklen > remain) {
					msg_info ("bad symbol name detected");
					return -1;
				}
				remain -= toklen;
				p += toklen;
				next_state = 4;
				state = 99;
				break;
			case 7:
				/* Parse message id */
				toklen = strcspn (p, "\r\n");
				*mid = malloc (toklen + 1);
				rmilter_strlcpy (*mid, p, toklen + 1);
				remain -= toklen;
				p += toklen;
				next_state = 4;
				state = 99;
				break;
			case 8:
				/* Parse subject line */
				toklen = strcspn (p, "\r\n");
				if (cur) {
					cur->subject = malloc (toklen + 1);
					rmilter_strlcpy (cur->subject, p, toklen + 1);
				}
				remain -= toklen;
				p += toklen;
				next_state = 4;
				state = 99;
				break;
			case 99:
				/* Skip spaces */
				if (isspace (*p)) {
					p ++;
					remain --;
				}
				else {
					state = next_state;
				}
				break;
			default:
				msg_err ("state machine breakage detected, state = %d, p = %s", state, p);
				return -1;
		}
	}

	if (cur != NULL) {
		TAILQ_INSERT_HEAD(res, cur, entry);
	}
	return 0;
}
Exemplo n.º 15
0
static void file_read_checks(const char *path)
{
	char buf1[16],buf2[8],buf3[32];
	struct iovec vec[3];
	int rc, f, cnt;
	off_t i;

	mlog("+open");
	f = open(path, O_RDONLY);
	if (f < 0)
		return;

	// first look at the file's attributes
	mlog("+fstat");
	rc = fstat(f, &sbuf);
#ifdef CHECK_XATTR
	mlog("+flistxattr");
	flistxattr(f, lbuf, MAXLISTBUF);
	mlog("+fgetxattr");
	fgetxattr(f, "selinux", lbuf, MAXLISTBUF);
#endif
//	readahead(f, NULL

	// Check reading
	mlog("+read");
	cnt = 0;
	while((read(f, buf3, sizeof(buf3)) > 0) && cnt < 1000)
		cnt++;

	// lseek around
	mlog("+lseek");
	if (rc == 0) 
		lseek(f, sbuf.st_size, SEEK_SET);
	lseek(f, 100000, SEEK_SET);
	lseek(f, 0, SEEK_SET);

	// vectored reads
	vec[0].iov_base = (void*)&buf1;
	vec[0].iov_len = sizeof(buf1);
	vec[1].iov_base = (void*)&buf2;
	vec[1].iov_len = sizeof(buf2);
	vec[2].iov_base = (void*)&buf3;
	vec[2].iov_len = sizeof(buf3);
	mlog("+readv");
	cnt = 0;
	while((readv(f, vec, 3) > 0) && cnt < 1000)
		cnt++;

	// check out pread syscall
	i = 0;
	mlog("+pread");
	cnt = 0;
	while ((pread(f, buf1, sizeof(buf1), i) > 0) && cnt < 1000) {
		i += sizeof(buf1)*2;
		cnt++;
	}

	// flock
	mlog("+flock");
	flock(f, LOCK_SH|LOCK_NB);
	flock(f, LOCK_UN);

	// fcntl ?

	// sendfile to localhost:discard
#if defined(__linux__)
	setup_socket();
	if (sfd >= 0) {
		mlog("+sendfile");
		lseek(f, 0, SEEK_SET);
		sendfile(sfd, f, NULL, rc ? 100000 : sbuf.st_size);
		close(sfd);
		sfd = -1;
	}
#endif

	// mmap each file
	if (rc == 0) {
		char *src;
		mlog("+mmap");
		src = mmap(0, sbuf.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
			f, 0);
		if (src != (char *)-1) {
			// Don't touch memory...or Mr. SIGBUS will visit you
			mlog("+munmap");
			munmap(src, sbuf.st_size);
		}
	}

	close(f);
}
Exemplo n.º 16
0
static void do_retr(session_t *sess)
{
	if(get_transfer_fd(sess) == 0)
                return;
	
	int fd = open(sess->arg, O_RDONLY);
	if(fd == -1)
	{
		ftp_reply(sess, FTP_FILEFAIL, "1Failed to open file.");
		return;
	}

	int ret;
	ret = lock_file_read(fd);	
	if(ret == -1)
	{
		ftp_reply(sess, FTP_FILEFAIL, "Failed to open file.");
                return;		
	}

	//device file can not be downloaded
	struct stat sbuf;
	ret = fstat(fd, &sbuf);
	if(!S_ISREG(sbuf.st_mode))
	{
		ftp_reply(sess, FTP_FILEFAIL, "Failed to open file.");
                return;
	}
	
	long long offset = sess->restart_pos;
        sess->restart_pos = 0;

	if(offset != 0)
	{
		ret = lseek(fd, offset, SEEK_SET);
		if(ret == -1)
		{
			ftp_reply(sess, FTP_FILEFAIL, "Failed to open file.");
	                return;
		}
	}

	char text[1024] = {0};
	if(sess->is_ascii)
	{
		sprintf(text, "Opening ASCII mode data conection for %s (%lld bytes).",
                sess->arg, (long long)sbuf.st_size);
	}
	else
	{
		sprintf(text, "Opening BINARY mode data conection for %s (%lld bytes).",
		sess->arg, (long long)sbuf.st_size);
	}	

        ftp_reply(sess, FTP_DATACONN, text);

	int flag = 0;
	long long bytes_to_send = sbuf.st_size;

	if(offset > bytes_to_send)
		bytes_to_send = 0;
	else
		bytes_to_send -= offset;

	sess->bw_transfer_start_sec = get_time_sec();
	sess->bw_transfer_start_usec = get_time_usec();

	while(bytes_to_send)
	{
		int num_this_time = bytes_to_send > 65536 ? 65536 : bytes_to_send;
		ret = sendfile(sess->data_fd, fd, NULL, num_this_time);
		if(ret == -1)
		{
			flag = 2;
			break;
		}
		
		limit_rate(sess, ret, 0);
		if(sess->abor_received)
		{
			flag = 2;
			break;
		}	

		bytes_to_send -= ret;
	}

        close(sess->data_fd);
        sess->data_fd = -1;
	close(fd);

	if(flag == 0)
        	ftp_reply(sess, FTP_TRANSFEROK, "Transfer complete.");

	else if(flag == 1)
		ftp_reply(sess, FTP_BADSENDFILE, "Failure reading from local file.");

	else if(flag == 2)
		ftp_reply(sess, FTP_BADSENDNET, "Failure writing to network stream.");

	check_abor(sess);
	start_cmdio_alarm();
}
Exemplo n.º 17
0
int tcpsendfile_ex(int sock, const char *filename, const int64_t file_offset, \
	const int64_t file_bytes, const int timeout, int64_t *total_send_bytes)
{
	int fd;
	int64_t send_bytes;
	int result;
	int flags;
#ifdef USE_SENDFILE
   #if defined(OS_FREEBSD) || defined(OS_LINUX)
	off_t offset;
	#ifdef OS_LINUX
	int64_t remain_bytes;
	#endif
   #endif
#else
	int64_t remain_bytes;
#endif

	fd = open(filename, O_RDONLY);
	if (fd < 0)
	{
		*total_send_bytes = 0;
		return errno != 0 ? errno : EACCES;
	}

	flags = fcntl(sock, F_GETFL, 0);
	if (flags < 0)
	{
		*total_send_bytes = 0;
		return errno != 0 ? errno : EACCES;
	}

#ifdef USE_SENDFILE

	if (flags & O_NONBLOCK)
	{
		if (fcntl(sock, F_SETFL, flags & ~O_NONBLOCK) == -1)
		{
			*total_send_bytes = 0;
			return errno != 0 ? errno : EACCES;
		}
	}

#ifdef OS_LINUX
	/*
	result = 1;
	if (setsockopt(sock, SOL_TCP, TCP_CORK, &result, sizeof(int)) < 0)
	{
		logError("file: "__FILE__", line: %d, " \
			"setsockopt failed, errno: %d, error info: %s.", \
			__LINE__, errno, STRERROR(errno));
		close(fd);
		*total_send_bytes = 0;
		return errno != 0 ? errno : EIO;
	}
	*/

#define FILE_1G_SIZE    (1 * 1024 * 1024 * 1024)

	result = 0;
	offset = file_offset;
	remain_bytes = file_bytes;
	while (remain_bytes > 0)
	{
		if (remain_bytes > FILE_1G_SIZE)
		{
			send_bytes = sendfile(sock, fd, &offset, FILE_1G_SIZE);
		}
		else
		{
			send_bytes = sendfile(sock, fd, &offset, remain_bytes);
		}

		if (send_bytes <= 0)
		{
			result = errno != 0 ? errno : EIO;
			break;
		}

		remain_bytes -= send_bytes;
	}

	*total_send_bytes = file_bytes - remain_bytes;
#else
#ifdef OS_FREEBSD
	offset = file_offset;
	if (sendfile(fd, sock, offset, file_bytes, NULL, NULL, 0) != 0)
	{
		*total_send_bytes = 0;
		result = errno != 0 ? errno : EIO;
	}
	else
	{
		*total_send_bytes = file_bytes;
		result = 0;
	}
#endif
#endif

	if (flags & O_NONBLOCK)  //restore
	{
		if (fcntl(sock, F_SETFL, flags) == -1)
		{
			result = errno != 0 ? errno : EACCES;
		}
	}

#ifdef OS_LINUX
	close(fd);
	return result;
#endif

#ifdef OS_FREEBSD
	close(fd);
	return result;
#endif

#endif

	{
	char buff[FDFS_WRITE_BUFF_SIZE];
	int64_t remain_bytes;
	tcpsenddatafunc send_func;

	if (file_offset > 0 && lseek(fd, file_offset, SEEK_SET) < 0)
	{
		result = errno != 0 ? errno : EIO;
		close(fd);
		*total_send_bytes = 0;
		return result;
	}

	if (flags & O_NONBLOCK)
	{
		send_func = tcpsenddata_nb;
	}
	else
	{
		send_func = tcpsenddata;
	}
	
	result = 0;
	remain_bytes = file_bytes;
	while (remain_bytes > 0)
	{
		if (remain_bytes > sizeof(buff))
		{
			send_bytes = sizeof(buff);
		}
		else
		{
			send_bytes = remain_bytes;
		}

		if (read(fd, buff, send_bytes) != send_bytes)
		{
			result = errno != 0 ? errno : EIO;
			break;
		}

		if ((result=send_func(sock, buff, send_bytes, \
				timeout)) != 0)
		{
			break;
		}

		remain_bytes -= send_bytes;
	}

	*total_send_bytes = file_bytes - remain_bytes;
	}

	close(fd);
	return result;
}
Exemplo n.º 18
0
void main(int argc,char *argv[]) {
    int going=TRUE,forsok=2,car=1,x,connectbps, i, tmp;
    struct NodeType *nt;
    char *tmppscreen,commandstring[100], configname[50] = "NiKom:DatoCfg/SerNode.cfg";
    FILE *fil;
    if(argc>1) for(x=1; x<argc; x++) {
            if(argv[x][0]=='-') {
                if(argv[x][1]=='G') getty=TRUE;
                else if(argv[x][1]=='B') gettybps=atoi(&argv[x][2]);
                else if(argv[x][1]=='C') connectbps = atoi(&argv[x][2]);
            } else strcpy(configname,argv[x]);
        }
    if(!(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0)))
        cleanup(ERROR,"Kunde inte öppna intuition.library\n");
    if(!(UtilityBase=OpenLibrary("utility.library",37L)))
        cleanup(ERROR,"Kunde inte öppna utility.library\n");
    if(!(NiKomBase=OpenLibrary("nikom.library",0L)))
        cleanup(ERROR,"Kunde inte öppna nikom.library\n");
    if(!initnode(NODSER)) cleanup(ERROR,"Kunde inte registrera noden i Servern\n");
    if(!(nikomnodeport = CreateMsgPort()))
        cleanup(ERROR,"Kunde inte skapa NiKomNode-porten");
    sprintf(nikomnodeportnamn,"NiKomNode%d",nodnr);
    nikomnodeport->mp_Node.ln_Name = nikomnodeportnamn;
    nikomnodeport->mp_Node.ln_Pri = 1;
    AddPort(nikomnodeport);
    sprintf(rexxportnamn,"NiKomPreRexx%d",nodnr);
    if(!(rexxport=(struct MsgPort *)CreateMsgPort()))
        cleanup(ERROR,"Kunde inte öppna RexxPort\n");
    rexxport->mp_Node.ln_Name=rexxportnamn;
    rexxport->mp_Node.ln_Pri=50;
    AddPort(rexxport);
    if(!(RexxSysBase=(struct RsxLib *)OpenLibrary("rexxsyslib.library",0L)))
        cleanup(ERROR,"Kunde inte öppna rexxsyslib.library\n");
    getnodeconfig(configname);
    if(pubscreen[0]=='-') tmppscreen=NULL;
    else tmppscreen=pubscreen;
    if(!(NiKwind=openmywindow(tmppscreen)))
        cleanup(ERROR,"Kunde inte öppna fönstret\n");
    if(getty) dtespeed = gettybps;
    else dtespeed = highbaud;
    if(!OpenIO(NiKwind)) cleanup(ERROR,"Couldn't setup IO");
    strcpy(Servermem->nodid[nodnr],nodid);
    conreqtkn();
    serreqtkn();
    Delay(50);
    for(;;) {
        inloggad=-1;
        Servermem->idletime[nodnr] = time(NULL);
        Servermem->inloggad[nodnr]=-1;
        if(getty) Servermem->connectbps[nodnr] = connectbps;
        else waitconnect();
        Servermem->idletime[nodnr] = time(NULL);
        Servermem->inloggad[nodnr]=-2; /* Sätt till <Uppringd> för att även hantera -getty-fallet */
reloginspec:
        updateinactive();
        Servermem->inne[nodnr].flaggor = Servermem->cfg.defaultflags;
        if(!getty) Delay(100);
        Servermem->inne[nodnr].rader=0;
        Servermem->inne[nodnr].chrset = CHRS_LATIN1;
        sendfile("NiKom:Texter/Inlogg.txt");
        if(Servermem->cfg.ar.preinlogg) sendrexx(Servermem->cfg.ar.preinlogg);
        car=TRUE;
        Servermem->inne[nodnr].chrset = 0;
        memset(commandhistory,0,1000);
        going=1;
        while(going && going<=Servermem->cfg.logintries) {
            putstring("\r\nNamn: ",-1,0);
            if(getstring(EKO,40,NULL)) {
                car=FALSE;
                break;
            }
            if(!stricmp(inmat,Servermem->cfg.ny)
                    && !(Servermem->cfg.cfgflags & NICFG_CLOSEDBBS)) {
                tmp = RegisterNewUser();
                if(tmp == 2) {
                    goto panik;
                }
                car = tmp ? 0 : 1;
                going=FALSE;
            } else if((inloggad=parsenamn(inmat))>=0) {
                if(readuser(inloggad,&Servermem->inne[nodnr])) {
                    puttekn("Error reading user data.\r\n", -1);
                    goto panik;
                }
                // TODO: Extract password loop. Should be identical to in NiKomCon.c
                forsok=2;
                while(forsok) {
                    puttekn("\r\nLösen: ",-1);
                    if(Servermem->inne[nodnr].flaggor & STAREKOFLAG)
                    {
                        if(getstring(STAREKO,15,NULL)) {
                            car=FALSE;
                            break;
                        }
                    }
                    else
                    {
                        if(getstring(EJEKO,15,NULL)) {
                            car=FALSE;
                            break;
                        }
                    }
                    if(CheckPassword(inmat, Servermem->inne[nodnr].losen))
                    {
                        forsok=FALSE;
                        going=FALSE;
                    } else forsok--;
                }
                if(going && (Servermem->cfg.logmask & LOG_FAILINLOGG)) {
                    LogEvent(USAGE_LOG, WARN, "Nod %d, %s angivet som namn, fel lösen.",
                             nodnr, getusername(inloggad));
                }
                if(going) going++;
            } else if(inloggad==-1) puttekn("\r\nHittar ej namnet\r\n",-1);
        }
        if(!car) {
            if(getty) cleanup(OK,"");
            disconnect();
            continue;
        }
        if(going) {
            putstring("\n\n\rTyvärr. Du har försökt maximalt antal gånger att logga in. Kopplar ned.\n\r",-1,0);
            goto panik;      /* Urrk vad fult. :-) */
        }
        Servermem->inloggad[nodnr]=inloggad;
        Servermem->idletime[nodnr] = time(NULL);
        if((nt = selectNodeType()) == NULL) {
            goto panik;
        }
        abortinactive();
        abortserial();

        sprintf(commandstring,"%s -N%d -B%d %s",nt->path,nodnr,dtespeed,configname);
        CloseConsole();
        CloseWindow(NiKwind);
        NiKwind = NULL;
        RemPort(nikomnodeport);

        i = 0;
        if(Servermem->connectbps[nodnr] > 0)
        {
            while(Servermem->info.bps[i] != Servermem->connectbps[nodnr] && Servermem->info.bps[i] > 0 && i<49)
                i++;

            if(i<49)
            {
                if(Servermem->info.bps[i] == Servermem->connectbps[nodnr])
                    Servermem->info.antbps[i]++;
                else
                {
                    Servermem->info.bps[i] = Servermem->connectbps[nodnr];
                    Servermem->info.antbps[i]++;
                }
            }

            if(!(fil = fopen("NiKom:datocfg/sysinfo.dat","w")))
            {
                /* putstring("Kunde inte spara nya sysinfo.dat..\n",-1,0); */
            }

            if(fwrite((void *)&Servermem->info,sizeof(Servermem->info),1,fil) != 1)
            {
                /* putstring("Kunde inte skriva till nya sysinfo.dat....\n",-1,0); */
            }
            fclose(fil);
        }

        nodestate = SystemTags(commandstring, SYS_UserShell, TRUE, TAG_DONE);
        AddPort(nikomnodeport);
        if(!getty || (nodestate & NIKSTATE_RELOGIN)) {
            if(!(NiKwind = openmywindow(tmppscreen))) cleanup(ERROR,"Kunde inte öppna fönstret\n");
            OpenConsole(NiKwind);
        }
        serreqtkn();
        if(nodestate & NIKSTATE_RELOGIN) goto reloginspec;
panik:
        Delay(hangupdelay);
        if(getty) cleanup(OK,"");
        disconnect();
    }
}
int network_write_file_chunk_sendfile(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes) {
	chunk* const c = cq->first;
	ssize_t r;
	off_t offset;
	off_t toSend;

	force_assert(NULL != c);
	force_assert(FILE_CHUNK == c->type);
	force_assert(c->offset >= 0 && c->offset <= c->file.length);

	offset = c->file.start + c->offset;
	toSend = c->file.length - c->offset;
	if (toSend > *p_max_bytes) toSend = *p_max_bytes;

	if (0 == toSend) {
		chunkqueue_remove_finished_chunks(cq);
		return 0;
	}

	if (0 != network_open_file_chunk(srv, con, cq)) return -1;

	if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
		switch (errno) {
		case EAGAIN:
		case EINTR:
			break;
		case EPIPE:
		case ECONNRESET:
			return -2;
		case EINVAL:
		case ENOSYS:
	      #if defined(ENOTSUP) \
		&& (!defined(EOPNOTSUPP) || EOPNOTSUPP != ENOTSUP)
		case ENOTSUP:
	      #endif
	      #ifdef EOPNOTSUPP
		case EOPNOTSUPP:
	      #endif
	      #ifdef ESOCKTNOSUPPORT
		case ESOCKTNOSUPPORT:
	      #endif
	      #ifdef EAFNOSUPPORT
		case EAFNOSUPPORT:
	      #endif
		      #ifdef USE_MMAP
			return network_write_file_chunk_mmap(srv, con, fd, cq, p_max_bytes);
		      #else
			return network_write_file_chunk_no_mmap(srv, con, fd, cq, p_max_bytes);
		      #endif
		default:
			log_error_write(srv, __FILE__, __LINE__, "ssd",
					"sendfile failed:", strerror(errno), fd);
			return -1;
		}
	}

	if (r >= 0) {
		chunkqueue_mark_written(cq, r);
		*p_max_bytes -= r;
	}

	return (r > 0 && r == toSend) ? 0 : -3;
}
Exemplo n.º 20
0
/**
 * @function net.sendfile
 * 
 * ### Synopsis
 * 
 * net.sendFile(sock, path);
 * net.sendFile(sock, path, offset);
 * net.sendFile(sock, path, offset, size);
 * 
 * This function calls the OS sendfile() function to send a complete or partial file to the network entirely within kernel space.  It is a HUGE speed win for HTTP and FTP type servers.
 * 
 * @param {int} sock - file descriptor of socket to send the file to.
 * @param {string} path - file system path to file to send.
 * @param {int} offset - offset from beginning of file to send (for partial).  If omitted, the entire file is sent.
 * @param {int} size - number of bytes of the file to send.  If omitted, the remainder of the file is sent (or all of it).
 * 
 * ### Exceptions
 * An exception is thrown if the file cannot be opened or if there is a sendfile(2) OS call error.
 */
 static JSVAL net_sendfile (JSARGS args) {
    HandleScope handle_scope;
    int sock = args[0]->IntegerValue();
    String::AsciiValue filename(args[1]);
    off_t offset = 0;
    if (args.Length() > 2) {
        offset = args[2]->IntegerValue();
    }
    size_t size;
    if (args.Length() > 3) {
        size = args[3]->IntegerValue();
    }
    else 
	{
        struct stat buf;
        if (stat(*filename, &buf)) 
		{
            printf("%s\n", *filename);
            perror("SendFile stat");
			{ FILE* fp=fopen("c:\\error.txt", "a+b"); fprintf(fp, "%d", __LINE__); fclose(fp); }
            return handle_scope.Close(False());
        }
        size = buf.st_size - offset;
    }

#ifdef WIN32
	HANDLE fd = CreateFile(*filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN | FILE_ATTRIBUTE_NORMAL, NULL);
    if (fd == INVALID_HANDLE_VALUE) {
#else
    int fd = open(*filename, O_RDONLY);
    if (fd < 0) {
#endif
        return ThrowException(String::Concat(String::New("sendFile open Error: "), String::New(strerror(errno))));
    }

    while (size > 0) {
#ifdef __APPLE__
        off_t count = size;
        if (sendfile(fd, sock, offset, &count, NULL, 0) == -1) {
            close(fd);
            return ThrowException(String::Concat(String::New("sendFile Error: "), String::New(strerror(errno))));
        }
#else
#ifdef WIN32
		SetFilePointer(fd, offset, NULL, FILE_BEGIN);
		TransmitFile(sock, fd, size, 0, NULL, NULL,0);
		ssize_t count = size;
        if (count == -1) {
            CloseHandle(fd);
            return ThrowException(String::Concat(String::New("sendFile Error: "), String::New(strerror(errno))));
        }
#else
        ssize_t count = sendfile(sock, fd, &offset, size);
        if (count == -1) {
            close(fd);
            return ThrowException(String::Concat(String::New("sendFile Error: "), String::New(strerror(errno))));
        }
#endif
#endif
        size -= count;
        offset += count;
    }
#ifdef WIN32
	CloseHandle(fd);
    int flag = 0;
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof (flag));
    flag = 1;
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof (flag));
#else
    close(fd);
    int flag = 0;
    setsockopt(fd, IPPROTO_TCP, TCP_CORK, &flag, sizeof (flag));
    flag = 1;
    setsockopt(fd, IPPROTO_TCP, TCP_CORK, &flag, sizeof (flag));
#endif

    return Undefined();
}

void init_net_object () {
    HandleScope scope;

    Handle<ObjectTemplate>net = ObjectTemplate::New();
    net->Set(String::New("connect"), FunctionTemplate::New(net_connect));
    net->Set(String::New("listen"), FunctionTemplate::New(net_listen));
    net->Set(String::New("accept"), FunctionTemplate::New(net_accept));
    net->Set(String::New("remote_addr"), FunctionTemplate::New(net_remote_addr));
    net->Set(String::New("cork"), FunctionTemplate::New(net_cork));
    net->Set(String::New("close"), FunctionTemplate::New(net_close));
    net->Set(String::New("read"), FunctionTemplate::New(net_read));
    net->Set(String::New("write"), FunctionTemplate::New(net_write));
    net->Set(String::New("writeBuffer"), FunctionTemplate::New(net_writebuffer));
    net->Set(String::New("sendFile"), FunctionTemplate::New(net_sendfile));

	net->Set(String::New("duplicateSocket"), FunctionTemplate::New(net_duplicateSocket));
	net->Set(String::New("getSocketDescriptor"), FunctionTemplate::New(net_getSocketDescriptor));

    builtinObject->Set(String::New("net"), net);
}
Exemplo n.º 21
0
int main (int argc, char **argv)
{
    struct sockaddr_un sin1;
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    ssize_t bytes, res=0;
    ssize_t rtotal = 0;
    FILE *stream;
    int in_fd;
    struct stat buf;
    off_t off = 0;

    unlink ("server_socket");
    unlink ("src_sendfile_save");
    stream = fopen ("src_sendfile_save", "w");
    if (!stream) {
        perror ("fopen");
        exit (EXIT_FAILURE);
    }
    fclose (stream);

    if ((in_fd = open ("src", O_RDONLY)) < 0) {
        printf ("Can't open 'src' file");
        exit (EXIT_FAILURE);
    }
    if (fstat (in_fd, &buf) == -1) {
        printf ("Can't stat 'src' file\n");
        exit (EXIT_FAILURE);
    }
    printf ("Get file size are %u bytes\n", buf.st_size);

    server_sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
    if (server_sockfd < 0) {
        perror ("socket");
        exit (EXIT_FAILURE);
    }
    sin1.sun_family = AF_UNIX;
    strcpy (sin1.sun_path, "server_socket");

    server_len = sizeof (sin1);
    if (bind (server_sockfd, (struct sockaddr *)&sin1, server_len) < 0) {
        perror ("bind");
        exit (EXIT_FAILURE);
    }
    if (listen (server_sockfd, 5) < 0) {
        perror ("listen");
        exit (EXIT_FAILURE);
    }

    printf ("The server is waiting for client connect...\n");

    client_sockfd = accept (server_sockfd, (struct sockaddr *)&sin1, (socklen_t *)&client_len);

    if (client_sockfd == -1 ) {
        perror ("accept");
        exit (EXIT_FAILURE);
    }
    while (off < buf.st_size) {
        if ((res = sendfile (client_sockfd, in_fd, &off, buf.st_size)) < 0 ) {
            printf ("sendfile failed\n");
            exit (EXIT_FAILURE);
        } else {
            rtotal += res;
        }
    }

    printf ("server sendfile total %u bytes\n", rtotal);
    close (client_sockfd);
    unlink ("server_socket");
    return (0);
}
Exemplo n.º 22
0
static int
send_test(int connect_socket, struct sendfile_test test)
{
	struct test_header th;
	struct sf_hdtr hdtr, *hdtrp;
	struct iovec headers;
	char *header;
	ssize_t len;
	int length;
	off_t off;

	len = lseek(file_fd, 0, SEEK_SET);
	if (len != 0)
		FAIL_ERR("lseek")

	if (test.length == 0) {
		struct stat st;
		if (fstat(file_fd, &st) < 0)
			FAIL_ERR("fstat")
		length = st.st_size - test.offset;
	}
	else {
		length = test.length;
	}

	init_th(&th, test.hdr_length, test.offset, length);

	len = write(connect_socket, &th, sizeof(th));
	if (len != sizeof(th))
		return (-1);

	if (test.hdr_length != 0) {
		header = malloc(test.hdr_length);
		if (header == NULL)
			FAIL_ERR("malloc")

		hdtrp = &hdtr;
		bzero(&headers, sizeof(headers));
		headers.iov_base = header;
		headers.iov_len = test.hdr_length;
		bzero(&hdtr, sizeof(hdtr));
		hdtr.headers = &headers;
		hdtr.hdr_cnt = 1;
		hdtr.trailers = NULL;
		hdtr.trl_cnt = 0;
	} else {
		hdtrp = NULL;
		header = NULL;
	}

	if (sendfile(file_fd, connect_socket, test.offset, test.length, 
				hdtrp, &off, 0) < 0) {
		if (header != NULL)
			free(header);
		FAIL_ERR("sendfile")
	}

	if (length == 0) {
		struct stat sb;

		if (fstat(file_fd, &sb) == 0)
			length = sb.st_size - test.offset;
	}

	if (header != NULL)
		free(header);

	if (off != length)
		FAIL("offset != length")

	return (0);
}
Exemplo n.º 23
0
bool proxy_connection::loop(unsigned fd)
{
	size_t total = 0;
	size_t count;
	int error;
	bool ret;

	do {
		logger::instance().log(logger::LOG_DEBUG, "[proxy_connection::loop] (fd %d) State = %s.", fd, state_to_string(_M_state));

		switch (_M_state) {
			case CONNECTING_STATE:
				if (!_M_client) {
					return false;
				}

				if ((!socket_wrapper::get_socket_error(fd, error)) || (error)) {
					logger::instance().log(logger::LOG_WARNING, "(fd %d) Connection to backend failed with error: %d.", fd, error);

#if !PROXY
					_M_client->_M_rule->backends.connection_failed(fd);
#endif

					_M_client->_M_error = http_error::GATEWAY_TIMEOUT;
					_M_state = PREPARING_ERROR_PAGE_STATE;
				} else {
					if (!_M_client->_M_payload_in_memory) {
						socket_wrapper::cork(fd);
					}

					_M_state = SENDING_HEADERS_STATE;
				}

				break;
			case SENDING_HEADERS_STATE:
				if (!_M_writable) {
					return true;
				}

				if ((!_M_client->_M_payload_in_memory) || (_M_client->_M_request_body_size == 0)) {
					count = _M_out.count();

					ret = write(fd, total);
				} else {
					socket_wrapper::io_vector io_vector[2];

					io_vector[0].iov_base = _M_out.data();
					io_vector[0].iov_len = _M_out.count();

					io_vector[1].iov_base = _M_client->_M_in.data() + _M_client->_M_request_header_size;
					io_vector[1].iov_len = _M_client->_M_request_body_size;

					count = io_vector[0].iov_len + io_vector[1].iov_len;

					ret = writev(fd, io_vector, 2, total);
				}

				if (!ret) {
					_M_client->_M_error = http_error::GATEWAY_TIMEOUT;
					_M_state = PREPARING_ERROR_PAGE_STATE;
				} else {
					_M_client->_M_timestamp = now::_M_time;

					if (_M_outp == (off_t) count) {
						if (_M_client->_M_payload_in_memory) {
							if (!modify(fd, tcp_server::READ)) {
								_M_client->_M_error = http_error::INTERNAL_SERVER_ERROR;
								_M_state = PREPARING_ERROR_PAGE_STATE;
							} else {
								_M_client->_M_body.reset();

								_M_state = READING_STATUS_LINE_STATE;
							}
						} else {
							_M_outp = 0;

							_M_state = SENDING_BODY_STATE;
						}
					}
				}

				break;
			case SENDING_BODY_STATE:
				if (!_M_writable) {
					return true;
				}

				if (!sendfile(fd, _M_client->_M_tmpfile, _M_client->_M_request_body_size, total)) {
					_M_client->_M_error = http_error::GATEWAY_TIMEOUT;
					_M_state = PREPARING_ERROR_PAGE_STATE;
				} else {
					_M_client->_M_timestamp = now::_M_time;

					if (_M_outp == (off_t) _M_client->_M_request_body_size) {
						// We don't need the client's temporary file anymore.
						static_cast<http_server*>(_M_server)->_M_tmpfiles.close(_M_client->_M_tmpfile);
						_M_client->_M_tmpfile = -1;

						socket_wrapper::uncork(fd);

						if (!modify(fd, tcp_server::READ)) {
							_M_client->_M_error = http_error::INTERNAL_SERVER_ERROR;
							_M_state = PREPARING_ERROR_PAGE_STATE;
						} else {
							_M_client->_M_body.reset();

							_M_state = READING_STATUS_LINE_STATE;
						}
					}
				}

				break;
			case READING_STATUS_LINE_STATE:
				if (!_M_readable) {
					return true;
				}

				if (!read_status_line(fd, total)) {
					_M_state = PREPARING_ERROR_PAGE_STATE;
				}

				break;
			case READING_HEADERS_STATE:
				if (!_M_readable) {
					return true;
				}

				if (!read_headers(fd, total)) {
					_M_state = PREPARING_ERROR_PAGE_STATE;
				}

				break;
			case PROCESSING_RESPONSE_STATE:
				if (!process_response(fd)) {
					_M_state = PREPARING_ERROR_PAGE_STATE;
				}

				break;
			case READING_BODY_STATE:
				if (!_M_readable) {
					return true;
				}

				if (!read_body(fd, total)) {
					_M_state = PREPARING_ERROR_PAGE_STATE;
				}

				break;
			case READING_CHUNKED_BODY_STATE:
				if (!_M_readable) {
					return true;
				}

				if (!read_chunked_body(fd, total)) {
					_M_state = PREPARING_ERROR_PAGE_STATE;
				}

				break;
			case READING_UNKNOWN_SIZE_BODY_STATE:
				if (!_M_readable) {
					return true;
				}

				if (!read_unknown_size_body(fd, total)) {
					_M_state = PREPARING_ERROR_PAGE_STATE;
				}

				break;
			case PREPARING_ERROR_PAGE_STATE:
				if (!http_error::build_page(_M_client)) {
					return false;
				}

				_M_client->_M_response_header_size = _M_client->_M_out.count();

				if ((_M_client->_M_method == http_method::HEAD) || (_M_client->_M_bodyp->count() == 0)) {
					_M_client->_M_filesize = 0;
				} else {
					_M_client->_M_filesize = _M_client->_M_bodyp->count();
				}

				_M_client->_M_payload_in_memory = 1;

				_M_client->_M_in_ready_list = 1;

				_M_client->_M_state = http_connection::SENDING_BACKEND_HEADERS_STATE;

				return false;
			case RESPONSE_COMPLETED_STATE:
				if (!prepare_http_response(fd)) {
					_M_client->_M_error = http_error::INTERNAL_SERVER_ERROR;
					_M_state = PREPARING_ERROR_PAGE_STATE;
				} else {
					_M_client->_M_in_ready_list = 1;

					_M_client->_M_tmpfile = _M_tmpfile;
					_M_tmpfile = -1;

					_M_client->_M_state = http_connection::SENDING_BACKEND_HEADERS_STATE;

					if (!_M_client->_M_payload_in_memory) {
						socket_wrapper::cork(_M_fd);
					}

					return false;
				}

				break;
		}
	} while (!_M_in_ready_list);

	return true;
}
ngx_chain_t *
ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
    int              rc, flags;
    off_t            send, prev_send, sent;
    size_t           file_size;
    ssize_t          n;
    ngx_uint_t       eintr, eagain;
    ngx_err_t        err;
    ngx_buf_t       *file;
    ngx_event_t     *wev;
    ngx_chain_t     *cl;
    ngx_iovec_t      header, trailer;
    struct sf_hdtr   hdtr;
    struct iovec     headers[NGX_IOVS_PREALLOCATE];
    struct iovec     trailers[NGX_IOVS_PREALLOCATE];

    wev = c->write;

    if (!wev->ready) {
        return in;
    }

#if (NGX_HAVE_KQUEUE)

    if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) {
        (void) ngx_connection_error(c, wev->kq_errno,
                               "kevent() reported about an closed connection");
        wev->error = 1;
        return NGX_CHAIN_ERROR;
    }

#endif

    /* the maximum limit size is the maximum size_t value - the page size */

    if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
        limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
    }

    send = 0;
    eagain = 0;
    flags = 0;

    header.iovs = headers;
    header.nalloc = NGX_IOVS_PREALLOCATE;

    trailer.iovs = trailers;
    trailer.nalloc = NGX_IOVS_PREALLOCATE;

    for ( ;; ) {
        eintr = 0;
        prev_send = send;

        /* create the header iovec and coalesce the neighbouring bufs */

        cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log);

        if (cl == NGX_CHAIN_ERROR) {
            return NGX_CHAIN_ERROR;
        }

        send += header.size;

        if (cl && cl->buf->in_file && send < limit) {
            file = cl->buf;

            /* coalesce the neighbouring file bufs */

            file_size = (size_t) ngx_chain_coalesce_file(&cl, limit - send);

            send += file_size;

            /* create the trailer iovec and coalesce the neighbouring bufs */

            cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send, c->log);

            if (cl == NGX_CHAIN_ERROR) {
                return NGX_CHAIN_ERROR;
            }

            send += trailer.size;

            if (ngx_freebsd_use_tcp_nopush
                && c->tcp_nopush == NGX_TCP_NOPUSH_UNSET)
            {
                if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
                    err = ngx_socket_errno;

                    /*
                     * there is a tiny chance to be interrupted, however,
                     * we continue a processing without the TCP_NOPUSH
                     */

                    if (err != NGX_EINTR) {
                        wev->error = 1;
                        (void) ngx_connection_error(c, err,
                                                    ngx_tcp_nopush_n " failed");
                        return NGX_CHAIN_ERROR;
                    }

                } else {
                    c->tcp_nopush = NGX_TCP_NOPUSH_SET;

                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                                   "tcp_nopush");
                }
            }

            /*
             * sendfile() does unneeded work if sf_hdtr's count is 0,
             * but corresponding pointer is not NULL
             */

            hdtr.headers = header.count ? header.iovs : NULL;
            hdtr.hdr_cnt = header.count;
            hdtr.trailers = trailer.count ? trailer.iovs : NULL;
            hdtr.trl_cnt = trailer.count;

            /*
             * the "nbytes bug" of the old sendfile() syscall:
             * http://bugs.freebsd.org/33771
             */

            if (!ngx_freebsd_sendfile_nbytes_bug) {
                header.size = 0;
            }

            sent = 0;

#if (NGX_HAVE_AIO_SENDFILE)
            flags = c->aio_sendfile ? SF_NODISKIO : 0;
#endif

            rc = sendfile(file->file->fd, c->fd, file->file_pos,
                          file_size + header.size, &hdtr, &sent, flags);

            if (rc == -1) {
                err = ngx_errno;

                switch (err) {
                case NGX_EAGAIN:
                    eagain = 1;
                    break;

                case NGX_EINTR:
                    eintr = 1;
                    break;

#if (NGX_HAVE_AIO_SENDFILE)
                case NGX_EBUSY:
                    c->busy_sendfile = file;
                    break;
#endif

                default:
                    wev->error = 1;
                    (void) ngx_connection_error(c, err, "sendfile() failed");
                    return NGX_CHAIN_ERROR;
                }

                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
                               "sendfile() sent only %O bytes", sent);

            /*
             * sendfile() in FreeBSD 3.x-4.x may return value >= 0
             * on success, although only 0 is documented
             */

            } else if (rc >= 0 && sent == 0) {

                /*
                 * if rc is OK and sent equal to zero, then someone
                 * has truncated the file, so the offset became beyond
                 * the end of the file
                 */

                ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                         "sendfile() reported that \"%s\" was truncated at %O",
                         file->file->name.data, file->file_pos);

                return NGX_CHAIN_ERROR;
            }

            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
                           "sendfile: %d, @%O %O:%uz",
                           rc, file->file_pos, sent, file_size + header.size);

        } else {
            n = ngx_writev(c, &header);

            if (n == NGX_ERROR) {
                return NGX_CHAIN_ERROR;
            }

            sent = (n == NGX_AGAIN) ? 0 : n;
        }

        c->sent += sent;

        in = ngx_chain_update_sent(in, sent);

#if (NGX_HAVE_AIO_SENDFILE)
        if (c->busy_sendfile) {
            return in;
        }
#endif

        if (eagain) {

            /*
             * sendfile() may return EAGAIN, even if it has sent a whole file
             * part, it indicates that the successive sendfile() call would
             * return EAGAIN right away and would not send anything.
             * We use it as a hint.
             */

            wev->ready = 0;
            return in;
        }

        if (eintr) {
            send = prev_send + sent;
            continue;
        }

        if (send - prev_send != sent) {
            wev->ready = 0;
            return in;
        }

        if (send >= limit || in == NULL) {
            return in;
        }
    }
}
Exemplo n.º 25
0
void httpResponseStaticProc( httpHeader *req_header )
{
	
	int len,cllen,ctlen;
	char path[1024] =
			{0};
	headerOut header_out;
	memset( &header_out , 0 , sizeof( header_out ) );
	header_out.req = req_header;
	
	getFilePath( req_header->uri , path );
	struct stat stat_file;
	int ret = stat( path , &stat_file );
	
	if (ret < 0)
	{
		respErrorPage( &header_out , 404 );
		return;
	}
	
	createCommonHeader( &header_out , 200 );
	headerAppendLength( &header_out , stat_file.st_size );
	appendRespHeader( &header_out , HEADER_END_LINE );
	
	int nwritten = write( req_header->connfd , header_out.data , header_out.length );
	if (nwritten <= 0)
	{
		printf( "I/O error writing to client connfd=%d,len=%d: %s \n" ,
				req_header->connfd , header_out.length , strerror( errno ) );
		return;
	}
	
	if (req_header->nobody == AE_TRUE)
	{
		httpClose( req_header , 1 );
		return;
	}
	
	int fd = open( path , O_RDONLY );
	if (fd < 0)
	{
		printf( "Open file Error:%s,errno=%d \n" , strerror( errno ) , errno );
		return;
	}
	
	// setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on));
	off_t offset = 0;
	int force_close = 0;
	while (offset < stat_file.st_size)
	{
		int sendn =
				sendfile( req_header->connfd , fd , &offset , stat_file.st_size - offset );
		
		if (sendn < 0)
		{
			//如果socket缓冲区不可用,则挂起等待可用
			if (errno == EAGAIN || errno == EINTR)
			{
				if (anetHandup( req_header->connfd , 5000 , AE_WRITABLE ) < 0)
				{
					//如果超时,退出
					printf( "Sendfile anetHandup timeout.......\n" );
					force_close = 1;
					break;
				}
				else
				{
					//否则继续发送
					continue;
				}
			}
			else
			{
				break;
			}
		}
	}
	close( fd );
	httpClose( req_header , force_close );
}
Exemplo n.º 26
0
int main(int argc, char ** argv)
{
        int port;
        struct stat obj;
        int sock = -1;
        struct sockaddr_in address;
        struct hostent * host;
        int choice;
        char buf[100], command[5], filename[20], *f;
        int k, size, status;
        int filehandle;
        int len;

        /* checking commandline parameter */
        if (argc != 4)
        {
                printf("usage: %s <hostname> <port> <name>\n", argv[0]);
                return -1;
        }

        /* obtain port number */
        if (sscanf(argv[2], "%d", &port) <= 0)
        {
                fprintf(stderr, "%s: error: wrong parameter: port\n", argv[0]);
                return -2;
        }

        /* create socket */
        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (sock <= 0)
        {
                fprintf(stderr, "%s: error: cannot create socket\n", argv[0]);
                return -3;
        }

        /* connect to server */
        address.sin_family = AF_INET;
        address.sin_port = htons(port);
        host = gethostbyname(argv[1]);
        if (!host)
        {
                fprintf(stderr, "%s: error: unknown host %s\n", argv[0], argv[1]);
                return -4;
        }
        memcpy(&address.sin_addr, host->h_addr_list[0], host->h_length);
        if (connect(sock, (struct sockaddr *)&address, sizeof(address)))
        {
                fprintf(stderr, "%s: error: cannot connect to host %s\n", argv[0], argv[1]);
                return -5;
        }

        int i = 1;
        signal(SIGINT,sigproc); /* call signal function */
        while(1)
        {

            printf("\n***Welcome to C# File Repository System***\n");
            printf("\nMain Menu:\n1- Download\n2- Upload\n3- Current Path\n4- List\n5- Change Path\n6- Register\n7- Quit\n");
            printf("Enter a choice:");
            scanf("%d", &choice);
        switch(choice)
        {
        case 1:
          printf("\n***Download File***\n");
          printf("Enter filename to Download: ");
          scanf("%s", filename);
          strcpy(buf, "get ");
          strcat(buf, filename);
          send(sock, buf, 100, 0);
          recv(sock, &size, sizeof(int), 0);
            if(!size)
            {
              printf("No such file on the remote directory\n\n");
                break;
            }
            f = malloc(size);
            recv(sock, f, size, 0);
            printf("Downloading....\n\n");
            while(1)
            {
              filehandle = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
              if(filehandle == -1)
                {
                  sprintf(filename + strlen(filename), "%d", i);//needed only if same directory is used for both server and client
                }
              else break;
            }
            write(filehandle, f, size);
            close(filehandle);
            printf("Download completed\n\n");
            break;

        case 2:
          printf("\n***Upload File***\n");
          printf("Enter filename to put to server: ");
          scanf("%s", filename);
          filehandle = open(filename, O_RDONLY);
          if(filehandle == -1)
            {
              printf("No such file on the local directory\n\n");
              break;
            }
          printf("Uploading....\n\n");
          strcpy(buf, "put ");
          strcat(buf, filename);
          send(sock, buf, 100, 0);
          stat(filename, &obj);
          size = obj.st_size;
          send(sock, &size, sizeof(int), 0);
          sendfile(sock, filehandle, NULL, size);
          recv(sock, &status, sizeof(int), 0);
          if(status)
            printf("File stored successfully\n");
          else
            printf("File failed to be stored to remote machine\n");
          break;

        case 3:
          strcpy(buf, "pwd");
          send(sock, buf, 100, 0);
          recv(sock, buf, 100, 0);
          printf("\n***Current Path***\n");
          printf("Path: %s\n", buf);
          break;

        case 4:
          printf("\n***List of Current Directory***\n");
          strcpy(buf, "ls");
          send(sock, buf, 100, 0);
          recv(sock, &size, sizeof(int), 0);
          f = malloc(size);
          recv(sock, f, size, 0);
          filehandle = creat("temp.txt", O_WRONLY);
          system("chmod 666 temp.txt");
          write(filehandle, f, size);
          close(filehandle);
          printf("The remote directory listing is as follows:\n");
          printf("-------------------------------------------\n");
          system("cat temp.txt");
          printf("-------------------------------------------\n");
          break;

        case 5:
          strcpy(buf, "cd ");
          printf("\n***Change Path***\n");
          printf("Enter the path to change the remote directory: ");
          scanf("%s", buf + 3);
          send(sock, buf, 100, 0);
          recv(sock, &status, sizeof(int), 0);
          if(status)
            printf("Remote directory successfully changed\n");
          else
            printf("Remote directory failed to change\n");
          break;

        case 6:
            strcpy(buf, "register");
            send(sock, buf, 100, 0);
            char username[BUFSIZ],  password1[BUFSIZ],    /* Buffers for user input and comparison    */
                    password2[BUFSIZ], *pbuf;

            /* Get the username */
            printf("Username: "******"%s", username);
            strcpy(buf, username);
            strcat(buf, ":");

             do {

                    /* Get the password */
                    pbuf = getpass("Password: "******"stable" pointer */
                    sprintf(password1, "%s", pbuf);

                    /* Get the password */
                    pbuf = getpass("Enter Again: ");

                    /* Copy to a "stable" pointer */
                    sprintf(password2, "%s", pbuf);

                    /* See if the passwords are the same */
                    if(strcmp(password1, password2) != 0)
                        printf("\nPasswords do not match!\nTry again.\n\n");

                } while(strcmp(password1, password2) != 0);
                    strcat(buf, password2);
                    send(sock, buf, 100, 0);
                    recv(sock, &status, sizeof(int), 0);
                    if(status)
                        printf("User successfully registered\n");
                    else
                        printf("Error. Registration failed.\n");
            break;

        case 7:
            strcpy(buf, "quit");
            send(sock, buf, 100, 0);
            len = strlen(argv[3]);
            write(sock, &len, sizeof(int));
            write(sock, argv[3], len);
            printf("Successfully Disconnected.\nQuitting..\n");

            /* close socket */
            close(sock);

            return 0;


        }
    }

}
Exemplo n.º 27
0
int initbrevheader(int tillpers) {
        int length=0,x=0,lappnr;
        long tid,tempmott;
        struct tm *ts;
        struct User usr;
        char filnamn[40],*mottagare,tempbuf[10],*vemskrev;
        Servermem->action[nodnr] = SKRIVER;
        Servermem->varmote[nodnr] = -1;
        memset(&brevspar,0,sizeof(struct ReadLetter));
        if(tillpers==-1) {
                strcpy(brevspar.to,brevread.from);
                mottagare=brevread.to;
                while(mottagare[0]) {
                        tempmott=atoi(mottagare);
                        if(tempmott==inloggad || recisthere(brevspar.to,tempmott)) {
                                mottagare=hittaefter(mottagare);
                                continue;
                        }
                        sprintf(tempbuf," %d",tempmott);
                        strcat(brevspar.to,tempbuf);
                        mottagare=hittaefter(mottagare);
                }
                sprintf(brevspar.reply,"%d %d %s",senast_brev_anv,senast_brev_nr,brevread.from);
        } else {
                sprintf(brevspar.to,"%d",tillpers);
        }
        sprintf(brevspar.from,"%d",inloggad);
        readuser(atoi(brevspar.to),&usr);
        if(usr.flaggor & LAPPBREV) {
                puttekn("\r\n\n",-1);
                lappnr=atoi(brevspar.to);
                sprintf(filnamn,"NiKom:Users/%d/%d/Lapp",lappnr/100,lappnr);
                if(!access(filnamn,0)) sendfile(filnamn);
                puttekn("\r\n",-1);
        }
        time(&tid);
        ts=localtime(&tid);
        sprintf(brevspar.date,"%2d%02d%02d %02d:%02d",ts->tm_year,ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min);
        strcpy(brevspar.systemid,"NiKom");
        sprintf(outbuffer,"\r\n\nMöte: %s\r\n",Servermem->cfg.brevnamn);
        puttekn(outbuffer,-1);
        sprintf(outbuffer,"Lokalt brev,  %s\n\r",brevspar.date);
        puttekn(outbuffer,-1);
        sprintf(outbuffer,"Avsändare: %s\r\n",getusername(inloggad));
        puttekn(outbuffer,-1);
        if(brevspar.reply[0]) {
                vemskrev=hittaefter(hittaefter(brevspar.reply));
                sprintf(outbuffer,"Kommentar till en text av %s\r\n",getusername(atoi(vemskrev)));
                puttekn(outbuffer,-1);
        }
        mottagare=brevspar.to;
        while(mottagare[0]) {
                sprintf(outbuffer,"Mottagare: %s\n\r",getusername(atoi(mottagare)));
                puttekn(outbuffer,-1);
                mottagare=hittaefter(mottagare);
        }
        puttekn("Ärende: ",-1);
        if(tillpers==-1) {
                strcpy(brevspar.subject,brevread.subject);
                puttekn(brevspar.subject,-1);
        } else {
                if(getstring(EKO,40,NULL)) return(1);
                if(!inmat[0]) {
                        eka('\n');
                        return(2);
                }
                strcpy(brevspar.subject,inmat);
        }
        puttekn("\r\n",-1);
        if(Servermem->inne[nodnr].flaggor & STRECKRAD) {
                length=strlen(brevspar.subject);
                for(x=0;x<length+8;x++) outbuffer[x]='-';
                outbuffer[x]=0;
                puttekn(outbuffer,-1);
                puttekn("\r\n\n",-1);
        } else puttekn("\n",-1);
        return(0);
}
Exemplo n.º 28
0
/**
 * @short This shortcut returns the given file contents. 
 * 
 * It sets all the compilant headers (TODO), cache and so on.
 * 
 * This is the recomended way to send static files; it even can use sendfile Linux call 
 * if suitable (TODO).
 * 
 * It does no security checks, so caller must be security aware.
 */
onion_connection_status onion_shortcut_response_file(const char *filename, onion_request *request, onion_response *res){
	int fd=open(filename,O_RDONLY|O_CLOEXEC);
	
	if (fd<0)
		return OCS_NOT_PROCESSED;

	if(O_CLOEXEC == 0) { // Good compiler know how to cut this out
		int flags=fcntl(fd, F_GETFD);
		if (flags==-1){
			ONION_ERROR("Retrieving flags from file descriptor");
		}
		flags|=FD_CLOEXEC;
		if (fcntl(fd, F_SETFD, flags)==-1){
			ONION_ERROR("Setting O_CLOEXEC to file descriptor");
		}
	}
	
	struct stat st;
	if (stat(filename, &st)!=0){
		ONION_WARNING("File does not exist: %s",filename);
		close(fd);
		return OCS_NOT_PROCESSED;
	}
	
	if (S_ISDIR(st.st_mode)){
		close(fd);
		return OCS_NOT_PROCESSED;
	}
	
	size_t length=st.st_size;
	
	char etag[64];
	onion_shortcut_etag(&st, etag);
		
	const char *range=onion_request_get_header(request, "Range");
	if (range){
		strncat(etag,range,sizeof(etag)-1);
	}
	onion_response_set_header(res, "Etag", etag);
	
	if (range && strncmp(range,"bytes=",6)==0){
		onion_response_set_code(res, HTTP_PARTIAL_CONTENT);
		//ONION_DEBUG("Need just a range: %s",range);
		char tmp[1024];
		strncpy(tmp, range+6, 1024);
		char *start=tmp;
		char *end=tmp;
		while (*end!='-' && *end) end++;
		if (*end=='-'){
			*end='\0';
			end++;
			
			//ONION_DEBUG("Start %s, end %s",start,end);
			size_t ends, starts;
			if (*end)
				ends=atol(end);
			else
				ends=length;
			starts=atol(start);
			length=ends-starts+1;
			lseek(fd, starts, SEEK_SET);
			snprintf(tmp,sizeof(tmp),"bytes %d-%d/%d",(unsigned int)starts, (unsigned int)ends, (unsigned int)st.st_size);
			//onion_response_set_header(res, "Accept-Ranges","bytes");
			onion_response_set_header(res, "Content-Range",tmp);
		}
	}
	
	onion_response_set_length(res, length);
	onion_response_set_header(res, "Content-Type", onion_mime_get(filename) );
	ONION_DEBUG("Mime type is %s",onion_mime_get(filename));

  ONION_DEBUG0("Etag %s", etag);
  const char *prev_etag=onion_request_get_header(request, "If-None-Match");
  if (prev_etag && (strcmp(prev_etag, etag)==0)){
    ONION_DEBUG0("Not modified");
    onion_response_set_length(res, 0);
    onion_response_set_code(res, HTTP_NOT_MODIFIED);
    onion_response_write_headers(res);
    close(fd);
    return OCS_PROCESSED;
  }
	onion_response_write_headers(res);
	if ((onion_request_get_flags(request)&OR_HEAD) == OR_HEAD){ // Just head.
		length=0;
	}
	
	if (length){
#ifdef USE_SENDFILE
		if (request->connection.listen_point->write==(void*)onion_http_write){ // Lets have a house party! I can use sendfile!
			onion_response_write(res,NULL,0);
			ONION_DEBUG("Using sendfile");
			int r=sendfile(request->connection.fd, fd, NULL, length);
			ONION_DEBUG("Wrote %d, should be %d (%s)", r, length, r==length ? "ok" : "nok");
			if (r!=length || r<0){
				ONION_ERROR("Could not send all file (%s)", strerror(errno));
				close(fd);
				return OCS_INTERNAL_ERROR;
			}
			res->sent_bytes+=length;
			res->sent_bytes_total+=length;
		}
		else
#endif
		{ // Ok, no I cant, do it as always.
			int r=0,w;
			size_t tr=0;
			char tmp[4046];
			if (length>sizeof(tmp)){
				size_t max=length-sizeof(tmp);
				while( tr<max ){
					r=read(fd,tmp,sizeof(tmp));
					tr+=r;
					if (r<0)
						break;
					w=onion_response_write(res, tmp, r);
					if (w!=r){
						ONION_ERROR("Wrote less than read: write %d, read %d. Quite probably closed connection.",w,r);
						break;
					}
				}
			}
			if (sizeof(tmp) >= (length-tr)){
				r=read(fd, tmp, length-tr);
				w=onion_response_write(res, tmp, r);
				if (w!=r){
					ONION_ERROR("Wrote less than read: write %d, read %d. Quite probably closed connection.",w,r);
				}
			}
		}
	}
	close(fd);
	return OCS_PROCESSED;
}
Exemplo n.º 29
0
Arquivo: fs.c Projeto: 76765357/node
static ssize_t uv__fs_sendfile(uv_fs_t* req) {
  int in_fd;
  int out_fd;

  in_fd = req->flags;
  out_fd = req->file;

#if defined(__linux__) || defined(__sun)
  {
    off_t off;
    ssize_t r;

    off = req->off;
    r = sendfile(out_fd, in_fd, &off, req->len);

    /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
     * it still writes out data. Fortunately, we can detect it by checking if
     * the offset has been updated.
     */
    if (r != -1 || off > req->off) {
      r = off - req->off;
      req->off = off;
      return r;
    }

    if (errno == EINVAL ||
        errno == EIO ||
        errno == ENOTSOCK ||
        errno == EXDEV) {
      errno = 0;
      return uv__fs_sendfile_emul(req);
    }

    return -1;
  }
#elif defined(__FreeBSD__) || defined(__APPLE__)
  {
    off_t len;
    ssize_t r;

    /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in
     * non-blocking mode and not all data could be written. If a non-zero
     * number of bytes have been sent, we don't consider it an error.
     */
    len = 0;

#if defined(__FreeBSD__)
    r = sendfile(in_fd, out_fd, req->off, req->len, NULL, &len, 0);
#else
    r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
#endif

    if (r != -1 || len != 0) {
      req->off += len;
      return (ssize_t) len;
    }

    if (errno == EINVAL ||
        errno == EIO ||
        errno == ENOTSOCK ||
        errno == EXDEV) {
      errno = 0;
      return uv__fs_sendfile_emul(req);
    }

    return -1;
  }
#else
  return uv__fs_sendfile_emul(req);
#endif
}
Exemplo n.º 30
0
int
main(int argc, char *argv[])
{
    int c;
    extern int optind;
    const char *optlet = "v";
    int verbose = 0;
    int fd, rfd;
    char *file, *rfile;
    int i, ret;
    off_t off;
    pid_t pid;
    char* addr, *raddr;
    char buf[4096];
    void *first, *second;
    
    while ((c = getopt(argc, argv, optlet)) != EOF) {
	switch (c) {
	case 'v':
	    verbose = 1;
	    break;
	case '?':
	default:
	    usage(argv[0]);
	    return (1);
	}
    }
    
    if (optind == argc) {
	usage(argv[0]);
	return (1);
    }

    // verify that mmap to a busy location works
    printf("region allocation errors expected for next test\n");
    first = mmap(0, 4096, PROT_WRITE, MAP_ANONYMOUS, 0, 0);
    second = mmap(first, 4096, PROT_WRITE, MAP_ANONYMOUS, 0, 0);

    file = argv[optind];
    
    fd = open(file, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);

    if (fd == -1) {
	fprintf(stderr, "%s: open(): %s: %s\n", argv[0], file,
		strerror(errno));
	return (1);
    }

    verbose_out(verbose, "open() succeeded, going to mmap\n");
    
    addr = mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

    if (addr == MAP_FAILED) {
	fprintf(stderr, "%s: mmap(): %s: %s\n", argv[0], file,
		strerror(errno));
	return (1);
    }
    
    if (optind+1 < argc) {
	rfile = argv[optind+1];
    
	rfd = open(rfile, O_RDONLY, 0);

	if (rfd == -1) {
	    fprintf(stderr, "%s: open(): %s: %s\n", argv[0], rfile,
		    strerror(errno));
	    return (1);
	}

	verbose_out(verbose, "open() succeeded, going to mmap\n");

	raddr = mmap(0, 4096, PROT_READ, MAP_SHARED, rfd, 0);

	if (raddr == MAP_FAILED) {
	    fprintf(stderr, "%s: mmap(): %s: %s\n", argv[0], rfile,
		    strerror(errno));
	    return (1);
	}
    }  else {
	rfd = -1;
	rfile = 0; raddr = 0;		// prevent compile warnings
    }

    verbose_out(verbose, "It is going to write\n");
    for (i = 0; i < 4096; i++) {
	addr[i] = i;
    }
    verbose_out(verbose, "writing succeeded\n");

    verbose_out(verbose, "it's going to fork\n");

    if ((pid = fork()) == 0) {
	// child
	verbose_out(verbose, "fork() succeeded\n");
	for (i = 0; i < 4096; i++) {
	    if(addr[i] != (i&0xff)) {
		fprintf(stderr,
			"compare failed: byte %d contained %d\n",
			i, addr[i]);
		return (1);
	    }
	}
    
	off = lseek(fd, 0, SEEK_SET);
	if (off == -1) {
	    fprintf(stderr, "%s: lseek(): %s: %s\n", argv[0], file,
		    strerror(errno));
	    return (1);
	}
	if (off != 0) {
	    fprintf(stderr, "%s: lseek() didn't returned 0 as expected\n",
		    argv[0]);
	    return (1);
	}
	verbose_out(verbose, "lseek() in child succeeded\n");

	verbose_out(verbose, "Child is going to read\n");

	i = read(fd, buf, 4096);
	
	if (i == -1) {
	    fprintf(stderr, "%s: read(): %s: %s\n", argv[0], file,
		    strerror(errno));
	    return (1);
	} else if (i != 4096) {
	    fprintf(stderr, "%s: file length wrong", argv[0]);
	    return (1);
	}

	for (i = 0; i < 4096; i++) {
	    if(buf[i] != (i&0xff)) {
		fprintf(stderr,
			"compare failed: byte %d contained %d\n",
			i, buf[i]);
		return (1);
	    }
	}
    
	verbose_out(verbose, "reading in child process succeeded\n");

	if (rfd != -1) {
	    ssize_t count;
	    off_t offset;
	    
	    fprintf(stdout, "read of first line of %s\n", rfile);
	    for(i = 0;raddr[i] != '\n' && i < 128; i++) {
		buf[i] = raddr[i];
	    }
	    buf[i] = 0;
	    fprintf(stdout, "%s\n", buf);

	    // now test sendfile
	    ftruncate(fd, 0);
	    lseek(fd, 0, SEEK_SET);
	    offset = 0;
	    count = sendfile(fd, rfd, &offset, 1000000);
	    if(count == -1) {
		fprintf(stderr, "%s: sendfile(): %s: %s\n", argv[0], file,
			strerror(errno));
		return (1);
	    }
	}
	
	return 0;
    } else if (pid != -1) {
	i = wait(&ret);
	if (i == -1) {
	    fprintf(stderr, "%s: wait failed:%s\n", argv[0], strerror(errno));
	    return(1);
	}
    } else {
	    fprintf(stderr, "%s: fork failed:%s\n", argv[0], strerror(errno));
	    return(1);
    }

    if (!ret) {
	verbose_out(verbose, "Test succeeded.\n");
    }
    
    return (ret);
}