Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

tcp_listen.cpp

Go to the documentation of this file.
00001 /*
00002 **  ClanLib SDK
00003 **  Copyright (c) 1997-2005 The ClanLib Team
00004 **
00005 **  This software is provided 'as-is', without any express or implied
00006 **  warranty.  In no event will the authors be held liable for any damages
00007 **  arising from the use of this software.
00008 **
00009 **  Permission is granted to anyone to use this software for any purpose,
00010 **  including commercial applications, and to alter it and redistribute it
00011 **  freely, subject to the following restrictions:
00012 **
00013 **  1. The origin of this software must not be misrepresented; you must not
00014 **     claim that you wrote the original software. If you use this software
00015 **     in a product, an acknowledgment in the product documentation would be
00016 **     appreciated but is not required.
00017 **  2. Altered source versions must be plainly marked as such, and must not be
00018 **     misrepresented as being the original software.
00019 **  3. This notice may not be removed or altered from any source distribution.
00020 **
00021 **  Note: Some of the libraries ClanLib link to may have additional
00022 **  requirements or restrictions.
00023 **
00024 **  File Author(s):
00025 **
00026 **    Magnus Norddahl
00027 */
00028 
00029 #include "precomp.h"
00030 #include "tcp_listen.h"
00031 #include "tcp_connection.h"
00032 #include "exception.h"
00033 #include "event.h"
00034 #include "string_help.h"
00035 #include "socket_event_handler.h"
00036 #ifdef WIN32
00037 #include <winsock.h>
00038 #define socklen_t int
00039 #else
00040 #include <sys/types.h>
00041 #include <sys/socket.h>
00042 #include <sys/time.h>
00043 #include <sys/types.h>
00044 #include <unistd.h>
00045 #include <netinet/in.h>
00046 #include <arpa/inet.h>
00047 #include <netdb.h>
00048 #endif
00049 #include <iostream>
00050 
00052 // CL_TCPListen Construction:
00053 
00054 CL_TCPListen::CL_TCPListen(const CL_String &port, int queue_size, bool force_bind)
00055 : handle(-1), socket_event_handler(0), accept_event(0)
00056 {
00057         handle = socket(PF_INET, SOCK_STREAM, 0);
00058         if (handle == -1)
00059                 throw CL_Exception(TEXT("Socket create failed"));
00060 
00061         // force_bind: SO_REUSEADDR
00062 
00063         int portI = CL_StringHelp::text_to_int(port);
00064 
00065         sockaddr_in name;
00066         memset(&name, 0, sizeof(sockaddr_in));
00067         name.sin_family = AF_INET;
00068         name.sin_addr.s_addr = INADDR_ANY;
00069         name.sin_port = htons(portI);
00070 
00071         int res = ::bind(handle, (sockaddr *) &name, sizeof(sockaddr_in));
00072         if (res != -1)
00073                 res = ::listen(handle, queue_size);
00074         if (res == -1)
00075         {
00076                 #ifdef WIN32
00077                 closesocket(handle);
00078                 #else
00079                 close(handle);
00080                 #endif
00081                 throw CL_Exception(TEXT("Could not bind socket port ") + port);
00082         }
00083         
00084         socket_event_handler = new CL_SocketEventHandler(handle);
00085         accept_event = new CL_Event(socket_event_handler, CL_Event::type_socket_read);
00086 }
00087         
00088 CL_TCPListen::CL_TCPListen(const CL_String &address, const CL_String &port, int queue_size, bool force_bind)
00089 : handle(-1), socket_event_handler(0), accept_event(0)
00090 {
00091         std::string addressA = CL_StringHelp::text_to_local8(address);
00092         int portI = CL_StringHelp::text_to_int(port);
00093 
00094         int ip = inet_addr(addressA.c_str());
00095         if (ip == INADDR_NONE)
00096         {
00097                 hostent *host_info = gethostbyname(addressA.c_str());
00098                 if (host_info == NULL)
00099                         throw CL_Exception(TEXT("Could not lookup ") + address);
00100 
00101                 ip = *((int *) host_info->h_addr_list[0]);
00102         }
00103 
00104         handle = socket(PF_INET, SOCK_STREAM, 0);
00105         if (handle == -1)
00106                 throw CL_Exception(TEXT("Socket create failed"));
00107 
00108         sockaddr_in name;
00109         memset(&name, 0, sizeof(sockaddr_in));
00110         name.sin_family = AF_INET;
00111         name.sin_addr.s_addr = ip;
00112         name.sin_port = htons(portI);
00113 
00114         int res = ::bind(handle, (sockaddr *) &name, sizeof(sockaddr_in));
00115         if (res != -1)
00116                 res = ::listen(handle, queue_size);
00117         if (res == -1)
00118         {
00119                 #ifdef WIN32
00120                 closesocket(handle);
00121                 #else
00122                 close(handle);
00123                 #endif
00124                 throw CL_Exception(TEXT("Could not bind socket on ") + address + TEXT(" port ") + port);
00125         }
00126 
00127         socket_event_handler = new CL_SocketEventHandler(handle);
00128         accept_event = new CL_Event(socket_event_handler, CL_Event::type_socket_read);
00129 }
00130         
00131 CL_TCPListen::~CL_TCPListen()
00132 {
00133         delete accept_event;
00134         delete socket_event_handler;
00135 #ifdef WIN32
00136         closesocket(handle);
00137 #else
00138         close(handle);
00139 #endif
00140 }
00141 
00143 // CL_TCPListen Attributes:
00144 
00145 CL_Event *CL_TCPListen::get_accept_event()
00146 {
00147         return accept_event;
00148 }
00149 
00151 // CL_TCPListen Operations:
00152 
00153 CL_TCPConnection *CL_TCPListen::accept(int timeout)
00154 {
00155         // EAGAIN
00156         // O_NONBLOCK
00157 
00158         sockaddr_in name;
00159         memset(&name, 0, sizeof(sockaddr_in));
00160         name.sin_family = AF_INET;
00161         
00162         socklen_t size = sizeof(sockaddr_in);
00163 
00164 #ifdef WIN32
00165         SOCKET sock = ::accept(handle, (sockaddr *) &name, &size);
00166         if (sock == -1)
00167                 return 0;
00168 #else
00169         int sock = ::accept(handle, (sockaddr *) &name, &size);
00170         if (sock == -1)
00171                 return 0;
00172 #endif
00173         return new CL_TCPConnection(sock);
00174 }
00175 
00177 // CL_TCPListen Implementation:

Generated on Sat Feb 19 22:51:16 2005 for npcore by  doxygen 1.4.1