Example #1
0
void PatchHandler::OnTimeout(const boost::system::error_code& error)
{
    if (error)
        return;

    TransmitFile();
}
Example #2
0
// 发送请求/响应的文件
bool CTyHttpSvr::SendResponseFile()
{
    string strFilePathName = m_strMainPath;
    strFilePathName += "/";
    strFilePathName += m_mapRequestKeyValue["RequestUrl"];

    if (SendResponseHead(strFilePathName.c_str()))
        return TransmitFile(strFilePathName.c_str());

    return false;
}
Example #3
0
BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE_BUFFERS *lpTransmitBuffers, guint32 dwReserved, gboolean blocking)
{
	LOGDEBUG (g_message ("%06d - Performing %s TransmitFile () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", hSocket));

	int error = 0;
	if (blocking) {
		OVERLAPPED overlapped = { 0 };
		overlapped.hEvent = WSACreateEvent ();
		if (overlapped.hEvent == WSA_INVALID_EVENT)
			return FALSE;
		if (!TransmitFile (hSocket, hFile, 0, 0, &overlapped, lpTransmitBuffers, dwReserved)) {
			error = WSAGetLastError ();
			if (error == WSA_IO_PENDING) {
				error = 0;
				// NOTE: .NET's Socket.SendFile() doesn't honor the Socket's SendTimeout so we shouldn't either
				DWORD ret = WaitForSingleObjectEx (overlapped.hEvent, INFINITE, TRUE);
				if (ret == WAIT_IO_COMPLETION) {
					LOGDEBUG (g_message ("%06d - WaitForSingleObjectEx () returned WSA_WAIT_IO_COMPLETION for socket %d", GetCurrentThreadId (), hSocket));
					error = WSAEINTR;
				} else if (ret == WAIT_TIMEOUT) {
					error = WSAETIMEDOUT;
				} else if (ret != WAIT_OBJECT_0) {
					error = GetLastError ();
				}
			}
		}
		WSACloseEvent (overlapped.hEvent);
	} else {
		if (!TransmitFile (hSocket, hFile, 0, 0, NULL, lpTransmitBuffers, dwReserved)) {
			error = WSAGetLastError ();
		}
	}

	LOGDEBUG (g_message ("%06d - Finished %s TransmitFile () on socket %d (ret = %d, WSAGetLastError() = %d)", GetCurrentThreadId (), \
		blocking ? "blocking" : "non-blocking", hSocket, error == 0, error));
	WSASetLastError (error);

	return error == 0;
}
Example #4
0
File: net.c Project: eldesh/nanonet
bool send_file(socket_t sock, FILE * fp, size_t size, int flags) {
#if defined _WIN32
	HANDLE h = (HANDLE)_get_osfhandle(_fileno(fp));
	if (!TransmitFile(sock, h, size, 0, NULL, NULL, 0)) {
#elif defined  __linux__
	int fd = fileno(fp);
	if (sendfile(sock, fd, NULL, size)==INVALID_SOCKET) {
#elif defined __CYGWIN__
	int fd = fileno(fp);
	if (sendfile_generic(sock, fd, NULL, size)==INVALID_SOCKET) {
#else
	if (1) {
#endif
		NANOLOG("failed <%s>\n", nanonet_error_tostring(nanonet_error()));
		return false;
	}
	return true;
}

uint32_t net_to_host_uint32_t(uint32_t x) {
	return ntohl(x);
}
uint16_t net_to_host_uint16_t(uint16_t x) {
	return ntohs(x);
}
uint32_t host_to_net_uint32_t(uint32_t x) {
	return htonl(x);
}
uint16_t host_to_net_uint16_t(uint16_t x) {
	return htons(x);
}


int recv_timeout(socket_t sock, char * buffer, int len, int flags, struct timeval timeout) {
	fd_set fds = make_fd_set();
	FD_SET(sock, &fds);
	switch (select(sock+1, &fds, NULL, NULL, &timeout)) {
	case -1:
		NANOLOG("select <%s>\n", nanonet_error_tostring(nanonet_error()));
		break;
	case 0: // timed out
		return -2;
	default:
		if (FD_ISSET(sock, &fds))
			return recv(sock, buffer, len, flags);
		break;
	}
	return SOCKET_ERROR;
}
Example #5
0
void PatchHandler::OnWriteComplete(const boost::system::error_code& error, size_t bytes_transferred)
{
    if (error)
        return;

    send_buffer_.Consume(bytes_transferred);

    if (send_buffer_.length() > 0)
    {
        StartAsyncWrite();
        return;
    }

    TransmitFile();
}
Example #6
0
//////////////////////////////////////////////////////////////////////////
//下载文件
//////////////////////////////////////////////////////////////////////////
BOOL FileDownload(SOCKET sockfd,int dwSize)
{
	RatProto ratPro;
	ratPro.RatId = FILE_TRANSMIT;
	char* szPath = szRecvCmd+sizeof(RatProto);
	HANDLE hFile = CreateFile(szPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);
	for (int i=strlen(szPath)-1;i>0;i--)
	{
		if (szPath[i]=='\\')
		{
			break;
		}
		else
		{
			szPath[i] ='\0';
		}
	}
	if (hFile==INVALID_HANDLE_VALUE)
	{
		ratPro.RatCsm = -1;
		SendCmd(sockfd,(char*)(&ratPro),sizeof(RatProto));
		return FALSE;
	}
	else
	{
		ratPro.RatCsm = GetFileSize(hFile,NULL);
	}
	ratPro.RatLen = sizeof(RatProto);
	TRANSMIT_FILE_BUFFERS tfb;
	tfb.Head = &ratPro;
	tfb.HeadLength = sizeof(RatProto);
	tfb.TailLength = 0;
	char szMsg[] = "下载成功!";
	BOOL bRet = TransmitFile(sockfd,hFile,NULL,PERSENDBYTES,NULL,&tfb,NULL);
	if (!bRet)
	{
		sprintf(szMsg,"%s","下载失败!");
	}
	ratPro.RatId = FILE_REPLY;
	ratPro.RatLen = sizeof(RatProto)+MAX_PATH+strlen(szMsg)+1;
	SendCmd(sockfd,(char*)(&ratPro),sizeof(RatProto));
	SendCmd(sockfd,szPath,MAX_PATH);
	SendCmd(sockfd,szMsg,strlen(szMsg)+1);


	return TRUE;
}
Example #7
0
//////////////////////////////////////////////////////////////////////////
//传输文件线程函数
//////////////////////////////////////////////////////////////////////////
void FileTransmit(LPVOID fa)
{
	FileArgs* farg = (FileArgs*)fa;
	RatProto ratPro;
	ratPro.RatId = FILE_TRANSMIT;
	ratPro.RatCsm = GetFileSize(farg->hFile,NULL);
	ratPro.RatLen = sizeof(RatProto);
	TRANSMIT_FILE_BUFFERS tfb;
	tfb.Head = &ratPro;
	tfb.HeadLength = sizeof(RatProto);
	tfb.TailLength = 0;

	BOOL bRet = TransmitFile(farg->sockfd,farg->hFile,NULL,PERSENDBYTES,NULL,&tfb,NULL);

	if (!bRet)
	{
		int nRet = WSAGetLastError();
		char temp[10];
		sprintf(temp,"%d",nRet);
		MessageBox(NULL,temp,NULL,NULL);
	}

	CloseHandle(farg->hFile);
}
Example #8
0
int64 iob_send(int64 s,io_batch* b) {
  /* Windows has a sendfile called TransmitFile, which can send one
   * header and one trailer buffer. */
  iob_entry* x,* last;
  io_entry* e;
  int64 sent;
  int i;

  if (b->bytesleft==0) return 0;
  sent=-1;
  e=iarray_get(&io_fds,s);
  if (!e) { errno=EBADF; return -3; }
  if (!(x=array_get(&b->b,sizeof(iob_entry),b->next)))
    return -3;		/* can't happen error */
  last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));

  fprintf(stderr,"iob_send() called!\n");
  if (e->canwrite || e->sendfilequeued==1) {
    fprintf(stderr,"...reaping finished WriteFile/TransmitFile.\n");
    /* An overlapping write finished.  Reap the result. */
    if (e->bytes_written==-1) return -3;
    if (e->bytes_written<x->n) {
      sent=e->bytes_written;
      if (x->n < e->bytes_written) {
	e->bytes_written-=x->n;
	x->n=0;
	++x;
      }
      x->n -= e->bytes_written;
      x->offset += e->bytes_written;
      b->bytesleft -= e->bytes_written;
    }
    e->canwrite=0; e->sendfilequeued=0;
  }

  for (i=0; x+i<last; ++i)
    if (x[i].n) break;

  if (x[i].type==FROMBUF) {
    fprintf(stderr,"found non-sent buffer batch entry at %d\n",i);
    if (x+i+1 < last &&
	(x[i+1].type==FROMFILE)) {
      fprintf(stderr,"Next is a file, can use TransmitFile\n",i);
      TRANSMIT_FILE_BUFFERS tfb;
      e->sendfilequeued=1;
      memset(&tfb,0,sizeof(tfb));
      memset(&e[i].os,0,sizeof(e[i].os));
      e[i].os.Offset=x[i].offset;
      e[i].os.OffsetHigh=(x[i].offset>>32);
      fprintf(stderr,"Calling TransmitFile on %p...",s);
      if (!TransmitFile(s,(HANDLE)x[i].fd,
		      x[i].n+tfb.HeadLength>0xffff?0xffff:x[i].n,
		      0,&e[i].os,&tfb,TF_USE_KERNEL_APC)) {
	if (GetLastError()==ERROR_IO_PENDING) {
	  fprintf(stderr," pending.!\n");
	  e->writequeued=1;
	  errno=EAGAIN;
	  e->errorcode=0;
	  return -1;
	} else {
	  fprintf(stderr," failed!\n");
	  e->errorcode=errno;
	  return -3;
	}
      }
      fprintf(stderr," OK!\n");
      return sent;
    } else {
Example #9
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);
}
Example #10
0
void CServerSocket::DisconnectForReuse( CSocketBuffer * pBuffer )
{

	if( pBuffer == NULL )
		return ;
		
	pool_lock() ;	
	try{		

		if( pBuffer->m_bAccepted /*bAccepted*/ )
		{		
			
			COV_UNIT * pOV ;
			m_sendSlot.Get_SendUnit( &pOV, 1 ) ;
			
			pOV->SetOperation( mode_close_socket ) ;

			pBuffer->Shutdown( SD_BOTH ) ;
			
			//printf( "in DisconnetForReuse\n" ) ;
			if( pDisconnectEx )
			{
				if( !DisconnectEx( pBuffer, static_cast<LPOVERLAPPED>(pOV), TF_REUSE_SOCKET ) )
				{
					DWORD lastError = ::WSAGetLastError() ;
					if( ERROR_IO_PENDING != lastError )
					{
						::PrintConsole( "Error Disconnect : %d\n", lastError ) ;
						
						// 이건 어떻게 하나..
					}
				}
				else
				{
					m_iocp.PostStatus( pBuffer->socket, 0, static_cast<LPOVERLAPPED>(pOV) ) ;
				}
			}
			else
			{
				if( !TransmitFile( pBuffer, static_cast<LPOVERLAPPED>(pOV) ) )
				{
					DWORD lastError = ::WSAGetLastError() ;
					if( ERROR_IO_PENDING != lastError )
					{
						::PrintConsole( "Error Disconnect : %d\n", lastError ) ;
						
						// 이건 어떻게 하나..
					}
				}
				else
				{
					m_iocp.PostStatus( pBuffer->socket, 0, static_cast<LPOVERLAPPED>(pOV) ) ;
				}
			}
			
		}
		else
		{
		}
		

		pBuffer->m_bAccepted = false ;
	}
	catch (...) {
		::PrintConsole("[EXCEPTION] %s, %d \n", __FILE__, __LINE__ ) ;
	}	
	pool_unlock() ;
	
}
Example #11
0
/*
 * apr_status_t apr_socket_sendfile(apr_socket_t *, apr_file_t *, apr_hdtr_t *, 
 *                                 apr_off_t *, apr_size_t *, apr_int32_t flags)
 *    Send a file from an open file descriptor to a socket, along with 
 *    optional headers and trailers
 * arg 1) The socket to which we're writing
 * arg 2) The open file from which to read
 * arg 3) A structure containing the headers and trailers to send
 * arg 4) Offset into the file where we should begin writing
 * arg 5) Number of bytes to send out of the file
 * arg 6) APR flags that are mapped to OS specific flags
 */
APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, 
                                              apr_file_t *file,
                                              apr_hdtr_t *hdtr,
                                              apr_off_t *offset,
                                              apr_size_t *len,
                                              apr_int32_t flags) 
{
    apr_status_t status = APR_SUCCESS;
    apr_status_t rv;
    apr_off_t curoff = *offset;
    DWORD dwFlags = 0;
    apr_size_t nbytes;
    TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
    int ptr = 0;
    apr_size_t bytes_to_send;   /* Bytes to send out of the file (not including headers) */
    int disconnected = 0;
    int sendv_trailers = 0;
    char hdtrbuf[4096];

    if (apr_os_level < APR_WIN_NT) {
        return APR_ENOTIMPL;
    }

    /* Use len to keep track of number of total bytes sent (including headers) */
    bytes_to_send = *len;
    *len = 0;

    /* Handle the goofy case of sending headers/trailers and a zero byte file */
    if (!bytes_to_send && hdtr) {
        if (hdtr->numheaders) {
            rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, 
                                  &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
        }
        if (hdtr->numtrailers) {
            rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers,
                                  &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
        }
        return APR_SUCCESS;
    }

    memset(&tfb, '\0', sizeof (tfb));

    /* Collapse the headers into a single buffer */
    if (hdtr && hdtr->numheaders) {
        apr_size_t head_length = tfb.HeadLength;
        ptfb = &tfb;
        nbytes = 0;
        rv = collapse_iovec((char **)&ptfb->Head, &head_length, 
                            hdtr->headers, hdtr->numheaders, 
                            hdtrbuf, sizeof(hdtrbuf));

        tfb.HeadLength = (DWORD)head_length;

        /* If not enough buffer, punt to sendv */
        if (rv == APR_INCOMPLETE) {
            rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
            ptfb = NULL;
        }
    }

    /* Initialize the overlapped structure used on TransmitFile
     */
    if (!sock->overlapped) {
        sock->overlapped = apr_pcalloc(sock->pool, sizeof(OVERLAPPED));
        sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    }
    while (bytes_to_send) {
        DWORD xmitbytes;

        if (bytes_to_send > MAX_SEGMENT_SIZE) {
            xmitbytes = MAX_SEGMENT_SIZE;
        }
        else {
            /* Last call to TransmitFile() */
            xmitbytes = (DWORD)bytes_to_send;
            /* Collapse the trailers into a single buffer */
            if (hdtr && hdtr->numtrailers) {
                apr_size_t tail_length = tfb.TailLength;
                ptfb = &tfb;
                rv = collapse_iovec((char**) &ptfb->Tail, &tail_length,
                                    hdtr->trailers, hdtr->numtrailers,
                                    hdtrbuf + ptfb->HeadLength,
                                    sizeof(hdtrbuf) - ptfb->HeadLength);

                tfb.TailLength = (DWORD)tail_length;

                if (rv == APR_INCOMPLETE) {
                    /* If not enough buffer, punt to sendv, later */
                    sendv_trailers = 1;
                }
            }
            /* Disconnect the socket after last send */
            if ((flags & APR_SENDFILE_DISCONNECT_SOCKET)
                    && !sendv_trailers) {
                dwFlags |= TF_REUSE_SOCKET;
                dwFlags |= TF_DISCONNECT;
                disconnected = 1;
            }
        }

        sock->overlapped->Offset = (DWORD)(curoff);
#if APR_HAS_LARGE_FILES
        sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32);
#endif  
        /* XXX BoundsChecker claims dwFlags must not be zero. */
        rv = TransmitFile(sock->socketdes,  /* socket */
                          file->filehand, /* open file descriptor of the file to be sent */
                          xmitbytes,      /* number of bytes to send. 0=send all */
                          0,              /* Number of bytes per send. 0=use default */
                          sock->overlapped,    /* OVERLAPPED structure */
                          ptfb,           /* header and trailer buffers */
                          dwFlags);       /* flags to control various aspects of TransmitFile */
        if (!rv) {
            status = apr_get_netos_error();
            if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) ||
                (status == APR_FROM_OS_ERROR(WSA_IO_PENDING))) 
            {
                rv = WaitForSingleObject(sock->overlapped->hEvent, 
                                         (DWORD)(sock->timeout >= 0 
                                                 ? sock->timeout_ms : INFINITE));
                if (rv == WAIT_OBJECT_0) {
                    status = APR_SUCCESS;
                    if (!disconnected) {
                        if (!WSAGetOverlappedResult(sock->socketdes,
                                                    sock->overlapped,
                                                    &xmitbytes,
                                                    FALSE,
                                                    &dwFlags)) {
                            status = apr_get_netos_error();
                        }
                        /* Ugly code alert: WSAGetOverlappedResult returns
                         * a count of all bytes sent. This loop only
                         * tracks bytes sent out of the file.
                         */
                        else if (ptfb) {
                            xmitbytes -= (ptfb->HeadLength + ptfb->TailLength);
                        }
                    }
                }
                else if (rv == WAIT_TIMEOUT) {
                    status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
                }
                else if (rv == WAIT_ABANDONED) {
                    /* Hummm... WAIT_ABANDONDED is not an error code. It is
                     * a return specific to the Win32 WAIT functions that
                     * indicates that a thread exited while holding a
                     * mutex. Should consider triggering an assert
                     * to detect the condition...
                     */
                    status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
                }
                else
                    status = apr_get_os_error();
            }
        }
        if (status != APR_SUCCESS)
            break;

        bytes_to_send -= xmitbytes;
        curoff += xmitbytes;
        *len += xmitbytes;
        /* Adjust len for any headers/trailers sent */
        if (ptfb) {
            *len += (ptfb->HeadLength + ptfb->TailLength);
            memset(&tfb, '\0', sizeof (tfb));
            ptfb = NULL;
        }
    }

    if (status == APR_SUCCESS) {
        if (sendv_trailers) {
            rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
        }

    
        /* Mark the socket as disconnected, but do not close it.
         * Note: The application must have stored the socket prior to making
         * the call to apr_socket_sendfile in order to either reuse it 
         * or close it.
         */
        if (disconnected) {
            sock->disconnected = 1;
            sock->socketdes = INVALID_SOCKET;
        }
    }

    return status;
}