jserversocket.cpp 3.5 KB
/***************************************************************************
 *   Copyright (C) 2005 by Jeff Ferr                                       *
 *   root@sat                                                              *
 *                                                                         *
 *   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 "jserversocket.h"
#include "jioexception.h"
#include "jsocket.h"
#include <string.h>

namespace jsocket {

ServerSocket::ServerSocket(uint16_t port_, uint16_t backlog_, InetAddress *addr_)
{
    _local = NULL;

	if (addr_ == NULL) {
		InetAddress *a = InetAddress::GetLocalHost();
        
		addr_ = a;
	}

	CreateSocket();

	if (port_ != 0) {
		BindSocket(addr_, port_);
		ListenSocket(backlog_);
	} else {
		socklen_t len;

		ListenSocket(backlog_);

		if(getsockname(_fd, (sockaddr *)&_lsock, &len) < 0) {
			throw IOException("Connect error !");
		}
	}
}

ServerSocket::~ServerSocket()
{
    if (_local) {
        delete _local;
    }
}

/** Private */

void ServerSocket::CreateSocket()
{
	_fd = ::socket(AF_INET, SOCK_STREAM, 0);
    
	if (_fd < 0) {
		throw IOException("Create socket error");
	}
}

void ServerSocket::BindSocket(InetAddress *local_addr_, uint16_t local_port_)
{
	int opt = 1;
    
	_local = local_addr_;
    
	bzero(&_lsock, sizeof(_lsock));
    
	_lsock.sin_family = AF_INET;
	_lsock.sin_addr.s_addr = htonl(INADDR_ANY);
	_lsock.sin_port = htons(local_port_);
    
	setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR,(void*)&opt, sizeof(opt));
    
	if(::bind(_fd, (sockaddr *) &_lsock, sizeof(_lsock)) < 0) {
		throw IOException("Bind socket error !");
	}
}

void ServerSocket::ListenSocket(uint16_t backlog_)
{
	if (::listen(_fd, backlog_) < 0) {
		throw IOException("Listen port error !");
	}
}

/** End */

Socket * ServerSocket::Accept()
{
	socklen_t sock_size;
	int handler;
	
	sock_size = sizeof(_rsock);
	handler = ::accept(_fd, (sockaddr *) &_rsock, &sock_size);
    
	if (handler < 0) {
		throw IOException("Accept failed !");
    }
    
	Socket *s = new Socket::Socket(handler, _rsock);
    
	return s;
}

InetAddress * ServerSocket::GetInetAddress()
{
	return _local;
}

uint16_t ServerSocket::GetLocalPort()
{
	return ntohs(_lsock.sin_port);
}

void ServerSocket::Close()
{
	if (close(_fd) < 0) {
		throw IOException("Close socket error !");
	}
}

};