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

tcp_connection.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_connection.h"
00031 #include "exception.h"
00032 #include "string_help.h"
00033 #include "event.h"
00034 #include "socket_event_handler.h"
00035 #ifdef WIN32
00036 #include <winsock.h>
00037 #define socklen_t int
00038 #else
00039 #include <sys/types.h>
00040 #include <sys/socket.h>
00041 #include <sys/time.h>
00042 #include <sys/types.h>
00043 #include <unistd.h>
00044 #include <netinet/in.h>
00045 #include <arpa/inet.h>
00046 #include <netdb.h>
00047 #endif
00048 
00050 // CL_TCPConnection Construction:
00051 
00052 CL_TCPConnection::CL_TCPConnection()
00053 : handle(-1), socket_event_handler(0), read_event(0), write_event(0), exception_event(0)
00054 {
00055         handle = socket(PF_INET, SOCK_STREAM, 0);
00056         if (handle == -1)
00057                 throw CL_Exception(TEXT("Socket create failed"));
00058                 
00059         socket_event_handler = new CL_SocketEventHandler(handle);
00060         read_event = new CL_Event(socket_event_handler, CL_Event::type_socket_read);
00061         write_event = new CL_Event(socket_event_handler, CL_Event::type_socket_write);
00062         exception_event = new CL_Event(socket_event_handler, CL_Event::type_socket_exception);
00063 }
00064 
00065 #ifdef WIN32
00066 CL_TCPConnection::CL_TCPConnection(SOCKET socket_handle)
00067 : handle(socket_handle), socket_event_handler(0), read_event(0), write_event(0), exception_event(0)
00068 {
00069         if (handle == -1)
00070                 throw CL_Exception(TEXT("Invalid socket value"));
00071 
00072         socket_event_handler = new CL_SocketEventHandler(handle);
00073         read_event = new CL_Event(socket_event_handler, CL_Event::type_socket_read);
00074         write_event = new CL_Event(socket_event_handler, CL_Event::type_socket_write);
00075         exception_event = new CL_Event(socket_event_handler, CL_Event::type_socket_exception);
00076 }
00077 #else
00078 CL_TCPConnection::CL_TCPConnection(int socket_handle)
00079 : handle(socket_handle), socket_event_handler(0), read_event(0), write_event(0), exception_event(0)
00080 {
00081         if (handle == -1)
00082                 throw CL_Exception(TEXT("Invalid socket value"));
00083 
00084         socket_event_handler = new CL_SocketEventHandler(handle);
00085         read_event = new CL_Event(socket_event_handler, CL_Event::type_socket_read);
00086         write_event = new CL_Event(socket_event_handler, CL_Event::type_socket_write);
00087         exception_event = new CL_Event(socket_event_handler, CL_Event::type_socket_exception);
00088 }
00089 #endif
00090 
00091 CL_TCPConnection::~CL_TCPConnection()
00092 {
00093         delete exception_event;
00094         delete write_event;
00095         delete read_event;
00096         delete socket_event_handler;
00097 #ifdef WIN32
00098         closesocket(handle);
00099 #else
00100         close(handle);
00101 #endif
00102 }
00103 
00105 // CL_TCPConnection Attributes:
00106 
00107 CL_Event *CL_TCPConnection::get_read_event()
00108 {
00109         return read_event;
00110 }
00111         
00112 CL_Event *CL_TCPConnection::get_write_event()
00113 {
00114         return write_event;
00115 }
00116         
00117 CL_Event *CL_TCPConnection::get_exception_event()
00118 {
00119         return exception_event;
00120 }
00121 
00123 // CL_TCPConnection Operations:
00124 
00125 void CL_TCPConnection::connect(const CL_String &server, const CL_String &port)
00126 {
00127         CL_StringA server_a = CL_StringHelp::text_to_local8(server);
00128         int port_i = CL_StringHelp::text_to_int(port);
00129 
00130         int ip = inet_addr(server_a.c_str());
00131         if (ip == INADDR_NONE)
00132         {
00133                 hostent *host_info = gethostbyname(server_a.c_str());
00134                 if (host_info == NULL)
00135                         throw CL_Exception(TEXT("Could not lookup ") + server);
00136 
00137                 ip = *((int *) host_info->h_addr_list[0]);
00138         }
00139 
00140         sockaddr_in name;
00141         memset(&name, 0, sizeof(sockaddr_in));
00142         name.sin_family = AF_INET;
00143         name.sin_addr.s_addr = ip;
00144         name.sin_port = htons(port_i);
00145 
00146         int res = ::connect(handle, (sockaddr *) &name, sizeof(sockaddr_in));
00147         if (res == -1)
00148                 throw CL_Exception(TEXT("Could not connect to server."));
00149 }
00150 
00151 int CL_TCPConnection::send(const void *_data, int length, bool all)
00152 {
00153         const char *data = (const char *) _data;
00154         int pos = 0;
00155         while (pos < length)
00156         {
00157                 int res = ::send(handle, data+pos, length-pos, 0);
00158                 if (res == -1)
00159                         throw CL_Exception(TEXT("Write failed to socket!"));
00160 
00161                 pos += res;
00162                 if (!all)
00163                         return pos;
00164         }
00165         return pos;
00166 }
00167 
00168 int CL_TCPConnection::receive(void *_data, int len, bool all)
00169 {
00170         char *data = (char *) _data;
00171         int received = 0;
00172         while (received < len)
00173         {
00174                 int res = ::recv(handle, data+received, len-received, 0);
00175                 if (res == -1)
00176                         throw CL_Exception(TEXT("Read failed on socket!"));
00177 
00178                 received += res;
00179                 if (!all)
00180                         return received;
00181         }
00182         return received;
00183 }
00184 
00185 int CL_TCPConnection::peek(void *_data, int len)
00186 {
00187         char *data = (char *) _data;
00188         int received = 0;
00189         int res = ::recv(handle, data+received, len-received, MSG_PEEK);
00190         if (res == -1)
00191                 throw CL_Exception(TEXT("Read peek failed on socket!"));
00192         received += res;
00193         return received;
00194 }
00195 
00196 void CL_TCPConnection::send_line(const CL_StringA &line)
00197 {
00198         send(line.data(), (socklen_t) line.length());
00199         send("\r\n", 2);
00200 }
00201 
00202 CL_StringA CL_TCPConnection::receive_line()
00203 {
00204         char buffer[16*1024];
00205         CL_StringA line;
00206         while (line.length() < 128*1024)
00207         {
00208                 int received = peek(buffer, 16*1024);
00209                 for (int i=0; i<received; i++)
00210                 {
00211                         if (buffer[i] == '\n')
00212                         {
00213                                 receive(buffer, i+1);
00214                                 line.append(buffer, i+1);
00215                                 return line;
00216                         }
00217                 }
00218 
00219                 receive(buffer, received);
00220                 line.append(buffer, received);
00221         }
00222 
00223         throw CL_Exception(TEXT("Received over 128 kb of data from socket. Expected a single line reply!"));
00224         return CL_StringA();
00225 }
00226 
00228 // CL_TCPConnection Implementation:

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