mirror of https://github.com/aria2/aria2
				
				
				
			Added SocketCore, make Socket a handle class for SocketCore.
							parent
							
								
									52634627bc
								
							
						
					
					
						commit
						8acb1181f9
					
				| 
						 | 
				
			
			@ -104,15 +104,15 @@ void DownloadEngine::waitData() {
 | 
			
		|||
  FD_ZERO(&wfds);
 | 
			
		||||
  int max = 0;
 | 
			
		||||
  for(vector<Socket*>::iterator itr = rsockets.begin(); itr != rsockets.end(); itr++) {
 | 
			
		||||
    FD_SET((*itr)->sockfd, &rfds);
 | 
			
		||||
    if(max < (*itr)->sockfd) {
 | 
			
		||||
      max = (*itr)->sockfd;
 | 
			
		||||
    FD_SET((*itr)->getSockfd(), &rfds);
 | 
			
		||||
    if(max < (*itr)->getSockfd()) {
 | 
			
		||||
      max = (*itr)->getSockfd();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  for(vector<Socket*>::iterator itr = wsockets.begin(); itr != wsockets.end(); itr++) {
 | 
			
		||||
    FD_SET((*itr)->sockfd, &wfds);
 | 
			
		||||
    if(max < (*itr)->sockfd) {
 | 
			
		||||
      max = (*itr)->sockfd;
 | 
			
		||||
    FD_SET((*itr)->getSockfd(), &wfds);
 | 
			
		||||
    if(max < (*itr)->getSockfd()) {
 | 
			
		||||
      max = (*itr)->getSockfd();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  tv.tv_sec = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
bin_PROGRAMS = aria2c
 | 
			
		||||
aria2c_SOURCES = main.cc
 | 
			
		||||
SRCS =  Socket.cc Socket.h\
 | 
			
		||||
	SocketCore.cc SocketCore.h\
 | 
			
		||||
	Command.h\
 | 
			
		||||
	AbstractCommand.cc AbstractCommand.h\
 | 
			
		||||
	InitiateConnectionCommandFactory.cc InitiateConnectionCommandFactory.h\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,6 +51,7 @@ ARFLAGS = cru
 | 
			
		|||
libaria2c_a_AR = $(AR) $(ARFLAGS)
 | 
			
		||||
libaria2c_a_LIBADD =
 | 
			
		||||
am__objects_1 = libaria2c_a-Socket.$(OBJEXT) \
 | 
			
		||||
	libaria2c_a-SocketCore.$(OBJEXT) \
 | 
			
		||||
	libaria2c_a-AbstractCommand.$(OBJEXT) \
 | 
			
		||||
	libaria2c_a-InitiateConnectionCommandFactory.$(OBJEXT) \
 | 
			
		||||
	libaria2c_a-DownloadCommand.$(OBJEXT) \
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +181,7 @@ sysconfdir = @sysconfdir@
 | 
			
		|||
target_alias = @target_alias@
 | 
			
		||||
aria2c_SOURCES = main.cc
 | 
			
		||||
SRCS = Socket.cc Socket.h\
 | 
			
		||||
	SocketCore.cc SocketCore.h\
 | 
			
		||||
	Command.h\
 | 
			
		||||
	AbstractCommand.cc AbstractCommand.h\
 | 
			
		||||
	InitiateConnectionCommandFactory.cc InitiateConnectionCommandFactory.h\
 | 
			
		||||
| 
						 | 
				
			
			@ -317,6 +319,7 @@ distclean-compile:
 | 
			
		|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SimpleLogger.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SleepCommand.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Socket.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SocketCore.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Util.Po@am__quote@
 | 
			
		||||
 | 
			
		||||
.cc.o:
 | 
			
		||||
| 
						 | 
				
			
			@ -347,6 +350,20 @@ libaria2c_a-Socket.obj: Socket.cc
 | 
			
		|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 | 
			
		||||
@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Socket.obj `if test -f 'Socket.cc'; then $(CYGPATH_W) 'Socket.cc'; else $(CYGPATH_W) '$(srcdir)/Socket.cc'; fi`
 | 
			
		||||
 | 
			
		||||
libaria2c_a-SocketCore.o: SocketCore.cc
 | 
			
		||||
@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SocketCore.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-SocketCore.Tpo" -c -o libaria2c_a-SocketCore.o `test -f 'SocketCore.cc' || echo '$(srcdir)/'`SocketCore.cc; \
 | 
			
		||||
@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libaria2c_a-SocketCore.Tpo" "$(DEPDIR)/libaria2c_a-SocketCore.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SocketCore.Tpo"; exit 1; fi
 | 
			
		||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SocketCore.cc' object='libaria2c_a-SocketCore.o' libtool=no @AMDEPBACKSLASH@
 | 
			
		||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 | 
			
		||||
@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SocketCore.o `test -f 'SocketCore.cc' || echo '$(srcdir)/'`SocketCore.cc
 | 
			
		||||
 | 
			
		||||
libaria2c_a-SocketCore.obj: SocketCore.cc
 | 
			
		||||
@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SocketCore.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-SocketCore.Tpo" -c -o libaria2c_a-SocketCore.obj `if test -f 'SocketCore.cc'; then $(CYGPATH_W) 'SocketCore.cc'; else $(CYGPATH_W) '$(srcdir)/SocketCore.cc'; fi`; \
 | 
			
		||||
@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libaria2c_a-SocketCore.Tpo" "$(DEPDIR)/libaria2c_a-SocketCore.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SocketCore.Tpo"; exit 1; fi
 | 
			
		||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SocketCore.cc' object='libaria2c_a-SocketCore.obj' libtool=no @AMDEPBACKSLASH@
 | 
			
		||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 | 
			
		||||
@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SocketCore.obj `if test -f 'SocketCore.cc'; then $(CYGPATH_W) 'SocketCore.cc'; else $(CYGPATH_W) '$(srcdir)/SocketCore.cc'; fi`
 | 
			
		||||
 | 
			
		||||
libaria2c_a-AbstractCommand.o: AbstractCommand.cc
 | 
			
		||||
@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-AbstractCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-AbstractCommand.Tpo" -c -o libaria2c_a-AbstractCommand.o `test -f 'AbstractCommand.cc' || echo '$(srcdir)/'`AbstractCommand.cc; \
 | 
			
		||||
@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libaria2c_a-AbstractCommand.Tpo" "$(DEPDIR)/libaria2c_a-AbstractCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-AbstractCommand.Tpo"; exit 1; fi
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										128
									
								
								src/Socket.cc
								
								
								
								
							
							
						
						
									
										128
									
								
								src/Socket.cc
								
								
								
								
							| 
						 | 
				
			
			@ -20,145 +20,63 @@
 | 
			
		|||
 */
 | 
			
		||||
/* copyright --> */
 | 
			
		||||
#include "Socket.h"
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include "DlRetryEx.h"
 | 
			
		||||
#include "DlAbortEx.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
Socket::Socket():sockfd(-1) {}
 | 
			
		||||
Socket::Socket() {
 | 
			
		||||
  core = new SocketCore();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Socket::Socket(const Socket& s) {
 | 
			
		||||
  sockfd = dup(s.sockfd);
 | 
			
		||||
  core = s.core;
 | 
			
		||||
  core->use++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Socket::~Socket() {
 | 
			
		||||
  closeConnection();
 | 
			
		||||
  core->use--;
 | 
			
		||||
  if(core->use == 0) {
 | 
			
		||||
    delete core;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Socket& Socket::operator=(const Socket& s) {
 | 
			
		||||
  if(this != &s) {
 | 
			
		||||
    closeConnection();
 | 
			
		||||
    sockfd = dup(s.sockfd);
 | 
			
		||||
    core->use--;
 | 
			
		||||
    if(core->use == 0) {
 | 
			
		||||
      delete core;
 | 
			
		||||
    }
 | 
			
		||||
    core = s.core;
 | 
			
		||||
    core->use++;
 | 
			
		||||
  }
 | 
			
		||||
  return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::establishConnection(string host, int port) {
 | 
			
		||||
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
  if(sockfd >= 0) {
 | 
			
		||||
    socklen_t sockopt = 1;
 | 
			
		||||
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0) {
 | 
			
		||||
      close(sockfd);
 | 
			
		||||
      sockfd = -1;
 | 
			
		||||
      throw new DlAbortEx(strerror(errno));
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
      throw new DlAbortEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  struct sockaddr_in sockaddr;
 | 
			
		||||
  memset((char*)&sockaddr, 0, sizeof(sockaddr));
 | 
			
		||||
  sockaddr.sin_family = AF_INET;
 | 
			
		||||
  sockaddr.sin_port = htons(port);
 | 
			
		||||
  if(inet_aton(host.c_str(), &sockaddr.sin_addr)) {
 | 
			
		||||
    // ok
 | 
			
		||||
  } else {
 | 
			
		||||
    struct addrinfo ai;
 | 
			
		||||
    ai.ai_flags = 0;
 | 
			
		||||
    ai.ai_family = PF_INET;
 | 
			
		||||
    ai.ai_socktype = SOCK_STREAM;
 | 
			
		||||
    ai.ai_protocol = 0; 
 | 
			
		||||
    ai.ai_addr = (struct sockaddr*)&sockaddr;
 | 
			
		||||
    struct addrinfo* res;
 | 
			
		||||
    int ec;
 | 
			
		||||
    if((ec = getaddrinfo(host.c_str(), NULL, &ai, &res)) != 0) {
 | 
			
		||||
      throw new DlAbortEx(gai_strerror(ec));
 | 
			
		||||
    }
 | 
			
		||||
    sockaddr.sin_addr = ((struct sockaddr_in*)res->ai_addr)->sin_addr;
 | 
			
		||||
    freeaddrinfo(res);
 | 
			
		||||
  }
 | 
			
		||||
  // make socket non-blocking mode
 | 
			
		||||
  int flags = fcntl(sockfd, F_GETFL, 0);
 | 
			
		||||
  fcntl(sockfd, F_SETFL, flags|O_NONBLOCK);
 | 
			
		||||
  if(connect(sockfd, (struct sockaddr*)&sockaddr, (socklen_t)sizeof(sockaddr)) == -1 && errno != EINPROGRESS) {
 | 
			
		||||
    throw new DlAbortEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
  core->establishConnection(host, port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::setNonBlockingMode() {
 | 
			
		||||
  int flags = fcntl(sockfd, F_GETFL, 0);
 | 
			
		||||
  fcntl(sockfd, F_SETFL, flags&~O_NONBLOCK);
 | 
			
		||||
  core->setNonBlockingMode();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::closeConnection() {
 | 
			
		||||
  if(sockfd != -1) {
 | 
			
		||||
    close(sockfd);
 | 
			
		||||
    sockfd = -1;
 | 
			
		||||
  }
 | 
			
		||||
  core->closeConnection();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Socket::isWritable(int timeout) {
 | 
			
		||||
  fd_set fds;
 | 
			
		||||
  FD_ZERO(&fds);
 | 
			
		||||
  FD_SET(sockfd, &fds);
 | 
			
		||||
 | 
			
		||||
  struct timeval tv;
 | 
			
		||||
  tv.tv_sec = timeout;
 | 
			
		||||
  tv.tv_usec = 0;
 | 
			
		||||
 | 
			
		||||
  int r = select(sockfd+1, NULL, &fds, NULL, &tv);
 | 
			
		||||
  if(r == 1) {
 | 
			
		||||
    return true;
 | 
			
		||||
  } else if(r == 0) {
 | 
			
		||||
    // time out
 | 
			
		||||
    return false;
 | 
			
		||||
  } else {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
  return core->isWritable(timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Socket::isReadable(int timeout) {
 | 
			
		||||
  fd_set fds;
 | 
			
		||||
  FD_ZERO(&fds);
 | 
			
		||||
  FD_SET(sockfd, &fds);
 | 
			
		||||
 | 
			
		||||
  struct timeval tv;
 | 
			
		||||
  tv.tv_sec = timeout;
 | 
			
		||||
  tv.tv_usec = 0;
 | 
			
		||||
 | 
			
		||||
  int r = select(sockfd+1, &fds, NULL, NULL, &tv);
 | 
			
		||||
  if(r == 1) {
 | 
			
		||||
    return true;
 | 
			
		||||
  } else if(r == 0) {
 | 
			
		||||
    // time out
 | 
			
		||||
    return false;
 | 
			
		||||
  } else {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
  return core->isReadable(timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::writeData(const char* data, int len, int timeout) {
 | 
			
		||||
  if(!isWritable(timeout) || send(sockfd, data, (size_t)len, 0) != len) {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
  core->writeData(data, len, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::readData(char* data, int& len, int timeout) {
 | 
			
		||||
  if(!isReadable(timeout) || (len = recv(sockfd, data, (size_t)len, 0)) < 0) {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
  core->readData(data, len, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::peekData(char* data, int& len, int timeout) {
 | 
			
		||||
  if(!isReadable(timeout) || (len = recv(sockfd, data, (size_t)len, MSG_PEEK)) < 0) {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
  core->peekData(data, len, timeout);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,13 +23,14 @@
 | 
			
		|||
#define _D_SOCKET_H_
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "SocketCore.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
class Socket {
 | 
			
		||||
public:
 | 
			
		||||
private:
 | 
			
		||||
  // socket endpoint descriptor
 | 
			
		||||
  int sockfd;
 | 
			
		||||
  SocketCore* core;
 | 
			
		||||
public:
 | 
			
		||||
  Socket();
 | 
			
		||||
  Socket(const Socket& s);
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +38,8 @@ public:
 | 
			
		|||
 | 
			
		||||
  Socket& operator=(const Socket& s);
 | 
			
		||||
 | 
			
		||||
  int getSockfd() const { return core->sockfd; }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Connects to the server named host and the destination port is port.
 | 
			
		||||
   * This method make socket non-blocking mode.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,152 @@
 | 
			
		|||
/* <!-- copyright */
 | 
			
		||||
/*
 | 
			
		||||
 * aria2 - a simple utility for downloading files faster
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2006 Tatsuhiro Tsujikawa
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
/* copyright --> */
 | 
			
		||||
#include "SocketCore.h"
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include "DlRetryEx.h"
 | 
			
		||||
#include "DlAbortEx.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
SocketCore::SocketCore():sockfd(-1), use(1) {}
 | 
			
		||||
 | 
			
		||||
SocketCore::~SocketCore() {
 | 
			
		||||
  closeConnection();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketCore::establishConnection(string host, int port) {
 | 
			
		||||
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
  if(sockfd >= 0) {
 | 
			
		||||
    socklen_t sockopt = 1;
 | 
			
		||||
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0) {
 | 
			
		||||
      close(sockfd);
 | 
			
		||||
      sockfd = -1;
 | 
			
		||||
      throw new DlAbortEx(strerror(errno));
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
      throw new DlAbortEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  struct sockaddr_in sockaddr;
 | 
			
		||||
  memset((char*)&sockaddr, 0, sizeof(sockaddr));
 | 
			
		||||
  sockaddr.sin_family = AF_INET;
 | 
			
		||||
  sockaddr.sin_port = htons(port);
 | 
			
		||||
  if(inet_aton(host.c_str(), &sockaddr.sin_addr)) {
 | 
			
		||||
    // ok
 | 
			
		||||
  } else {
 | 
			
		||||
    struct addrinfo ai;
 | 
			
		||||
    ai.ai_flags = 0;
 | 
			
		||||
    ai.ai_family = PF_INET;
 | 
			
		||||
    ai.ai_socktype = SOCK_STREAM;
 | 
			
		||||
    ai.ai_protocol = 0; 
 | 
			
		||||
    ai.ai_addr = (struct sockaddr*)&sockaddr;
 | 
			
		||||
    struct addrinfo* res;
 | 
			
		||||
    int ec;
 | 
			
		||||
    if((ec = getaddrinfo(host.c_str(), NULL, &ai, &res)) != 0) {
 | 
			
		||||
      throw new DlAbortEx(gai_strerror(ec));
 | 
			
		||||
    }
 | 
			
		||||
    sockaddr.sin_addr = ((struct sockaddr_in*)res->ai_addr)->sin_addr;
 | 
			
		||||
    freeaddrinfo(res);
 | 
			
		||||
  }
 | 
			
		||||
  // make socket non-blocking mode
 | 
			
		||||
  int flags = fcntl(sockfd, F_GETFL, 0);
 | 
			
		||||
  fcntl(sockfd, F_SETFL, flags|O_NONBLOCK);
 | 
			
		||||
  if(connect(sockfd, (struct sockaddr*)&sockaddr, (socklen_t)sizeof(sockaddr)) == -1 && errno != EINPROGRESS) {
 | 
			
		||||
    throw new DlAbortEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketCore::setNonBlockingMode() {
 | 
			
		||||
  int flags = fcntl(sockfd, F_GETFL, 0);
 | 
			
		||||
  fcntl(sockfd, F_SETFL, flags&~O_NONBLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketCore::closeConnection() {
 | 
			
		||||
  if(sockfd != -1) {
 | 
			
		||||
    close(sockfd);
 | 
			
		||||
    sockfd = -1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SocketCore::isWritable(int timeout) {
 | 
			
		||||
  fd_set fds;
 | 
			
		||||
  FD_ZERO(&fds);
 | 
			
		||||
  FD_SET(sockfd, &fds);
 | 
			
		||||
 | 
			
		||||
  struct timeval tv;
 | 
			
		||||
  tv.tv_sec = timeout;
 | 
			
		||||
  tv.tv_usec = 0;
 | 
			
		||||
 | 
			
		||||
  int r = select(sockfd+1, NULL, &fds, NULL, &tv);
 | 
			
		||||
  if(r == 1) {
 | 
			
		||||
    return true;
 | 
			
		||||
  } else if(r == 0) {
 | 
			
		||||
    // time out
 | 
			
		||||
    return false;
 | 
			
		||||
  } else {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SocketCore::isReadable(int timeout) {
 | 
			
		||||
  fd_set fds;
 | 
			
		||||
  FD_ZERO(&fds);
 | 
			
		||||
  FD_SET(sockfd, &fds);
 | 
			
		||||
 | 
			
		||||
  struct timeval tv;
 | 
			
		||||
  tv.tv_sec = timeout;
 | 
			
		||||
  tv.tv_usec = 0;
 | 
			
		||||
 | 
			
		||||
  int r = select(sockfd+1, &fds, NULL, NULL, &tv);
 | 
			
		||||
  if(r == 1) {
 | 
			
		||||
    return true;
 | 
			
		||||
  } else if(r == 0) {
 | 
			
		||||
    // time out
 | 
			
		||||
    return false;
 | 
			
		||||
  } else {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketCore::writeData(const char* data, int len, int timeout) {
 | 
			
		||||
  if(!isWritable(timeout) || send(sockfd, data, (size_t)len, 0) != len) {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketCore::readData(char* data, int& len, int timeout) {
 | 
			
		||||
  if(!isReadable(timeout) || (len = recv(sockfd, data, (size_t)len, 0)) < 0) {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketCore::peekData(char* data, int& len, int timeout) {
 | 
			
		||||
  if(!isReadable(timeout) || (len = recv(sockfd, data, (size_t)len, MSG_PEEK)) < 0) {
 | 
			
		||||
    throw new DlRetryEx(strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
/* <!-- copyright */
 | 
			
		||||
/*
 | 
			
		||||
 * aria2 - a simple utility for downloading files faster
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2006 Tatsuhiro Tsujikawa
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
/* copyright --> */
 | 
			
		||||
#ifndef _D_SOCKET_CORE_H_
 | 
			
		||||
#define _D_SOCKET_CORE_H_
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
class SocketCore {
 | 
			
		||||
  friend class Socket;
 | 
			
		||||
private:
 | 
			
		||||
  // socket endpoint descriptor
 | 
			
		||||
  int sockfd;
 | 
			
		||||
  // reference counter for this object.
 | 
			
		||||
  int use;
 | 
			
		||||
public:
 | 
			
		||||
  SocketCore();
 | 
			
		||||
  ~SocketCore();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Connects to the server named host and the destination port is port.
 | 
			
		||||
   * This method make socket non-blocking mode.
 | 
			
		||||
   * To make the socket blocking mode, call setNonBlockingMode() after
 | 
			
		||||
   * the connection is established.
 | 
			
		||||
   */
 | 
			
		||||
  void establishConnection(string host, int port);
 | 
			
		||||
 | 
			
		||||
  void setNonBlockingMode();
 | 
			
		||||
 | 
			
		||||
  // Closes the connection which this socket object has
 | 
			
		||||
  void closeConnection();
 | 
			
		||||
 | 
			
		||||
  // examines whether the socket of this SocketCore object is available for writing.
 | 
			
		||||
  // returns true if the socket is available for writing, otherwise returns false.
 | 
			
		||||
  bool isWritable(int timeout);
 | 
			
		||||
 | 
			
		||||
  // examines whether the socket of this SocketCore object is available for reading.
 | 
			
		||||
  // returns true if the socket is available for reading, otherwise returns false.
 | 
			
		||||
  bool isReadable(int timeout);
 | 
			
		||||
 | 
			
		||||
  // writes characters into the socket. data is a pointer pointing the first
 | 
			
		||||
  // byte of the data and len is the length of the data.
 | 
			
		||||
  void writeData(const char* data, int len, int timeout = 5);
 | 
			
		||||
 | 
			
		||||
  // Reads up to len bytes from this socket.
 | 
			
		||||
  // data is a pointer pointing the first
 | 
			
		||||
  // byte of the data, which must be allocated before this method is called.
 | 
			
		||||
  // len is the size of the allocated memory. When this method returns
 | 
			
		||||
  // successfully, len is replaced by the size of the read data.
 | 
			
		||||
  void readData(char* data, int& len, int timeout = 5);
 | 
			
		||||
  // Reads up to len bytes from this socket, but bytes are not removed from
 | 
			
		||||
  // this socket.
 | 
			
		||||
  void peekData(char* data, int& len, int timeout = 5);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // _D_SOCKET_CORE_H_
 | 
			
		||||
		Loading…
	
		Reference in New Issue