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);
|
FD_ZERO(&wfds);
|
||||||
int max = 0;
|
int max = 0;
|
||||||
for(vector<Socket*>::iterator itr = rsockets.begin(); itr != rsockets.end(); itr++) {
|
for(vector<Socket*>::iterator itr = rsockets.begin(); itr != rsockets.end(); itr++) {
|
||||||
FD_SET((*itr)->sockfd, &rfds);
|
FD_SET((*itr)->getSockfd(), &rfds);
|
||||||
if(max < (*itr)->sockfd) {
|
if(max < (*itr)->getSockfd()) {
|
||||||
max = (*itr)->sockfd;
|
max = (*itr)->getSockfd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(vector<Socket*>::iterator itr = wsockets.begin(); itr != wsockets.end(); itr++) {
|
for(vector<Socket*>::iterator itr = wsockets.begin(); itr != wsockets.end(); itr++) {
|
||||||
FD_SET((*itr)->sockfd, &wfds);
|
FD_SET((*itr)->getSockfd(), &wfds);
|
||||||
if(max < (*itr)->sockfd) {
|
if(max < (*itr)->getSockfd()) {
|
||||||
max = (*itr)->sockfd;
|
max = (*itr)->getSockfd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tv.tv_sec = 1;
|
tv.tv_sec = 1;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
bin_PROGRAMS = aria2c
|
bin_PROGRAMS = aria2c
|
||||||
aria2c_SOURCES = main.cc
|
aria2c_SOURCES = main.cc
|
||||||
SRCS = Socket.cc Socket.h\
|
SRCS = Socket.cc Socket.h\
|
||||||
|
SocketCore.cc SocketCore.h\
|
||||||
Command.h\
|
Command.h\
|
||||||
AbstractCommand.cc AbstractCommand.h\
|
AbstractCommand.cc AbstractCommand.h\
|
||||||
InitiateConnectionCommandFactory.cc InitiateConnectionCommandFactory.h\
|
InitiateConnectionCommandFactory.cc InitiateConnectionCommandFactory.h\
|
||||||
|
|
|
@ -51,6 +51,7 @@ ARFLAGS = cru
|
||||||
libaria2c_a_AR = $(AR) $(ARFLAGS)
|
libaria2c_a_AR = $(AR) $(ARFLAGS)
|
||||||
libaria2c_a_LIBADD =
|
libaria2c_a_LIBADD =
|
||||||
am__objects_1 = libaria2c_a-Socket.$(OBJEXT) \
|
am__objects_1 = libaria2c_a-Socket.$(OBJEXT) \
|
||||||
|
libaria2c_a-SocketCore.$(OBJEXT) \
|
||||||
libaria2c_a-AbstractCommand.$(OBJEXT) \
|
libaria2c_a-AbstractCommand.$(OBJEXT) \
|
||||||
libaria2c_a-InitiateConnectionCommandFactory.$(OBJEXT) \
|
libaria2c_a-InitiateConnectionCommandFactory.$(OBJEXT) \
|
||||||
libaria2c_a-DownloadCommand.$(OBJEXT) \
|
libaria2c_a-DownloadCommand.$(OBJEXT) \
|
||||||
|
@ -180,6 +181,7 @@ sysconfdir = @sysconfdir@
|
||||||
target_alias = @target_alias@
|
target_alias = @target_alias@
|
||||||
aria2c_SOURCES = main.cc
|
aria2c_SOURCES = main.cc
|
||||||
SRCS = Socket.cc Socket.h\
|
SRCS = Socket.cc Socket.h\
|
||||||
|
SocketCore.cc SocketCore.h\
|
||||||
Command.h\
|
Command.h\
|
||||||
AbstractCommand.cc AbstractCommand.h\
|
AbstractCommand.cc AbstractCommand.h\
|
||||||
InitiateConnectionCommandFactory.cc InitiateConnectionCommandFactory.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-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-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-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@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Util.Po@am__quote@
|
||||||
|
|
||||||
.cc.o:
|
.cc.o:
|
||||||
|
@ -347,6 +350,20 @@ libaria2c_a-Socket.obj: Socket.cc
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @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-Socket.obj `if test -f 'Socket.cc'; then $(CYGPATH_W) 'Socket.cc'; else $(CYGPATH_W) '$(srcdir)/Socket.cc'; fi`
|
@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
|
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@ 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
|
@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 --> */
|
/* copyright --> */
|
||||||
#include "Socket.h"
|
#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) {
|
Socket::Socket(const Socket& s) {
|
||||||
sockfd = dup(s.sockfd);
|
core = s.core;
|
||||||
|
core->use++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket::~Socket() {
|
Socket::~Socket() {
|
||||||
closeConnection();
|
core->use--;
|
||||||
|
if(core->use == 0) {
|
||||||
|
delete core;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket& Socket::operator=(const Socket& s) {
|
Socket& Socket::operator=(const Socket& s) {
|
||||||
if(this != &s) {
|
if(this != &s) {
|
||||||
closeConnection();
|
core->use--;
|
||||||
sockfd = dup(s.sockfd);
|
if(core->use == 0) {
|
||||||
|
delete core;
|
||||||
|
}
|
||||||
|
core = s.core;
|
||||||
|
core->use++;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::establishConnection(string host, int port) {
|
void Socket::establishConnection(string host, int port) {
|
||||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
core->establishConnection(host, port);
|
||||||
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 Socket::setNonBlockingMode() {
|
void Socket::setNonBlockingMode() {
|
||||||
int flags = fcntl(sockfd, F_GETFL, 0);
|
core->setNonBlockingMode();
|
||||||
fcntl(sockfd, F_SETFL, flags&~O_NONBLOCK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::closeConnection() {
|
void Socket::closeConnection() {
|
||||||
if(sockfd != -1) {
|
core->closeConnection();
|
||||||
close(sockfd);
|
|
||||||
sockfd = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Socket::isWritable(int timeout) {
|
bool Socket::isWritable(int timeout) {
|
||||||
fd_set fds;
|
return core->isWritable(timeout);
|
||||||
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 Socket::isReadable(int timeout) {
|
bool Socket::isReadable(int timeout) {
|
||||||
fd_set fds;
|
return core->isReadable(timeout);
|
||||||
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 Socket::writeData(const char* data, int len, int timeout) {
|
void Socket::writeData(const char* data, int len, int timeout) {
|
||||||
if(!isWritable(timeout) || send(sockfd, data, (size_t)len, 0) != len) {
|
core->writeData(data, len, timeout);
|
||||||
throw new DlRetryEx(strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::readData(char* data, int& len, int timeout) {
|
void Socket::readData(char* data, int& len, int timeout) {
|
||||||
if(!isReadable(timeout) || (len = recv(sockfd, data, (size_t)len, 0)) < 0) {
|
core->readData(data, len, timeout);
|
||||||
throw new DlRetryEx(strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::peekData(char* data, int& len, int timeout) {
|
void Socket::peekData(char* data, int& len, int timeout) {
|
||||||
if(!isReadable(timeout) || (len = recv(sockfd, data, (size_t)len, MSG_PEEK)) < 0) {
|
core->peekData(data, len, timeout);
|
||||||
throw new DlRetryEx(strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,14 @@
|
||||||
#define _D_SOCKET_H_
|
#define _D_SOCKET_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "SocketCore.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class Socket {
|
class Socket {
|
||||||
public:
|
private:
|
||||||
// socket endpoint descriptor
|
// socket endpoint descriptor
|
||||||
int sockfd;
|
SocketCore* core;
|
||||||
public:
|
public:
|
||||||
Socket();
|
Socket();
|
||||||
Socket(const Socket& s);
|
Socket(const Socket& s);
|
||||||
|
@ -37,6 +38,8 @@ public:
|
||||||
|
|
||||||
Socket& operator=(const Socket& s);
|
Socket& operator=(const Socket& s);
|
||||||
|
|
||||||
|
int getSockfd() const { return core->sockfd; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects to the server named host and the destination port is port.
|
* Connects to the server named host and the destination port is port.
|
||||||
* This method make socket non-blocking mode.
|
* 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