/*************************************************************************** * Copyright (C) 2007 by Lothar May * * * * 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. * ***************************************************************************/ #include #include #include #include #include #include #include using namespace std; ClientState::~ClientState() { } //----------------------------------------------------------------------------- ClientStateInit & ClientStateInit::Instance() { static ClientStateInit state; return state; } ClientStateInit::ClientStateInit() { } ClientStateInit::~ClientStateInit() { } int ClientStateInit::Process(ClientThread &client) { ClientData &data = client.GetData(); if (data.serverAddr.empty()) throw ClientException(ERR_SOCK_SERVERADDR_NOT_SET, 0); if (data.serverPort < 1024) throw ClientException(ERR_SOCK_INVALID_PORT, 0); data.sockfd = socket(data.addrFamily, SOCK_STREAM, 0); if (!IS_VALID_SOCKET(data.sockfd)) throw ClientException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); #if 0 unsigned long mode = 1; if (IOCTLSOCKET(data.sockfd, FIONBIO, &mode) == SOCKET_ERROR) throw ClientException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); #endif client.SetState(ClientStateResolve::Instance()); return MSG_SOCK_INIT_DONE; } //----------------------------------------------------------------------------- ClientStateResolve & ClientStateResolve::Instance() { static ClientStateResolve state; return state; } ClientStateResolve::ClientStateResolve() { } ClientStateResolve::~ClientStateResolve() { } int ClientStateResolve::Process(ClientThread &client) { ClientData &data = client.GetData(); data.clientAddr.ss_family = data.addrFamily; // Treat the server address as numbers first. if (socket_string_to_addr( data.serverAddr.c_str(), data.addrFamily, (struct sockaddr *)&data.clientAddr, data.GetServerAddrSize())) { // Success - but we still need to set the port. if (!socket_set_port(data.serverPort, data.addrFamily, (struct sockaddr *)&data.clientAddr, data.GetServerAddrSize())) throw ClientException(ERR_SOCK_SET_PORT_FAILED, 0); } else { // This did not work out - try name resolution. ostringstream tmpStr; tmpStr << data.serverPort; // TODO: start in a separate thread, since it is blocking. if (!socket_resolve( data.serverAddr.c_str(), tmpStr.str().c_str(), data.addrFamily, SOCK_STREAM, 0, (struct sockaddr *)&data.clientAddr, data.GetServerAddrSize())) { throw ClientException(ERR_SOCK_RESOLVE_FAILED, 0); } } client.SetState(ClientStateConnect::Instance()); return MSG_SOCK_RESOLVE_DONE; } //----------------------------------------------------------------------------- ClientStateConnect & ClientStateConnect::Instance() { static ClientStateConnect state; return state; } ClientStateConnect::ClientStateConnect() { } ClientStateConnect::~ClientStateConnect() { } int ClientStateConnect::Process(ClientThread &client) { ClientData &data = client.GetData(); if (!IS_VALID_CONNECT(connect(data.sockfd, (struct sockaddr *)&data.clientAddr, data.GetServerAddrSize()))) throw ClientException(ERR_SOCK_CONNECT_FAILED, SOCKET_ERRNO()); client.SetState(ClientStateFinal::Instance()); return MSG_SOCK_RESOLVE_DONE; } //----------------------------------------------------------------------------- ClientStateFinal & ClientStateFinal::Instance() { static ClientStateFinal state; return state; } ClientStateFinal::ClientStateFinal() { } ClientStateFinal::~ClientStateFinal() { } int ClientStateFinal::Process(ClientThread &client) { Thread::Msleep(10); return MSG_SOCK_INTERNAL_PENDING; }