00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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
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
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