00001
00002 #ifdef WIN32
00003 #pragma warning (disable:4786)
00004 #endif
00005
00006 #include "socket_generic.h"
00007 #include "API/Core/System/error.h"
00008
00010
00011
00012 CL_Socket::CL_Socket(int socket)
00013 : impl(new CL_Socket_Generic)
00014 {
00015 impl->add_ref();
00016 impl->sock = socket;
00017 }
00018
00019 CL_Socket::CL_Socket(CL_Socket::Type type)
00020 : impl(new CL_Socket_Generic)
00021 {
00022 impl->add_ref();
00023
00024 int in_type = SOCK_STREAM, in_proto = 0;
00025 switch (type)
00026 {
00027 case tcp: in_proto = SOCK_STREAM; break;
00028 case udp: in_proto = SOCK_DGRAM; break;
00029 }
00030
00031 impl->sock = socket(AF_INET, in_type, in_proto);
00032 if (impl->sock < 0) throw CL_Error("CL_Socket::CL_Socket failed");
00033 }
00034
00035 CL_Socket::CL_Socket(const CL_Socket ©)
00036 : impl(copy.impl)
00037 {
00038 impl->add_ref();
00039 }
00040
00041 CL_Socket::~CL_Socket()
00042 {
00043 if (impl) impl->release_ref();
00044 }
00045
00047
00048
00049 int CL_Socket::get_socket() const
00050 {
00051 return impl->sock;
00052 }
00053
00054 CL_EventTrigger *CL_Socket::get_read_trigger() const
00055 {
00056 if (impl->read == NULL) impl->read = impl->create_read_trigger();
00057 return impl->read;
00058 }
00059
00060 CL_EventTrigger *CL_Socket::get_write_trigger() const
00061 {
00062 if (impl->write == NULL) impl->write = impl->create_write_trigger();
00063 return impl->write;
00064 }
00065
00066 CL_EventTrigger *CL_Socket::get_exception_trigger() const
00067 {
00068 if (impl->exception == NULL) impl->exception = impl->create_exception_trigger();
00069 return impl->exception;
00070 }
00071
00072 CL_IPAddress CL_Socket::get_source_address() const
00073 {
00074 sockaddr_in addr_in;
00075 memset(&addr_in, 0, sizeof(addr_in));
00076 addr_in.sin_family = AF_INET;
00077
00078 int size = sizeof(sockaddr_in);
00079
00080 int result = getsockname(impl->sock, (sockaddr *) &addr_in, &size);
00081 if (result == 0) throw CL_Error("CL_Socket::get_source_address() failed.");
00082
00083 return CL_Socket_Generic::create_ip_address(addr_in);
00084 }
00085
00086 CL_IPAddress CL_Socket::get_dest_address() const
00087 {
00088 sockaddr_in addr_in;
00089 memset(&addr_in, 0, sizeof(addr_in));
00090 addr_in.sin_family = AF_INET;
00091
00092 int size = sizeof(sockaddr_in);
00093
00094 int result = getpeername(impl->sock, (sockaddr *) &addr_in, &size);
00095 if (result == 0) throw CL_Error("CL_Socket::get_dest_address() failed.");
00096
00097 return CL_Socket_Generic::create_ip_address(addr_in);
00098 }
00099
00100 CL_Signal_v0 &CL_Socket::sig_read_triggered()
00101 {
00102 return impl->sig_read_triggered;
00103 }
00104
00105 CL_Signal_v0 &CL_Socket::sig_write_triggered()
00106 {
00107 return impl->sig_write_triggered;
00108 }
00109
00110 CL_Signal_v0 &CL_Socket::sig_exception_triggered()
00111 {
00112 return impl->sig_exception_triggered;
00113 }
00114
00116
00117
00118 void CL_Socket::set_nonblocking(bool nonblocking)
00119 {
00120 #ifdef WIN32
00121 u_long argp = nonblocking ? 1 : 0;
00122 ioctlsocket(impl->sock, FIONBIO, &argp);
00123 #else
00124 fcntl(impl->sock, F_SETFL, O_NONBLOCK, nonblocking ? 1 : 0);
00125 #endif
00126 }
00127
00128 void CL_Socket::set_nodelay(bool nodelay)
00129 {
00130 static int sol_tcp = -1;
00131 if (sol_tcp == -1) sol_tcp = getprotobyname("tcp")->p_proto;
00132
00133 int value = nodelay ? 1 : 0;
00134 setsockopt(impl->sock, sol_tcp, TCP_NODELAY, (const char *) &value, sizeof(int));
00135 }
00136
00137 int CL_Socket::send(const void *data, int size)
00138 {
00139 int result = ::send(
00140 impl->sock,
00141 (const char *) data,
00142 size,
00143 0);
00144 if (result < 0) throw CL_Error("CL_Socket::send failed");
00145
00146 if (impl->write) impl->write->start_listen();
00147 return result;
00148 }
00149
00150 int CL_Socket::send(const void *data, int size, const CL_IPAddress &dest)
00151 {
00152 sockaddr_in addr_in = CL_Socket_Generic::create_sockaddr_in(dest);
00153
00154 int result = ::sendto(
00155 impl->sock,
00156 (const char *) data,
00157 size,
00158 0,
00159 (const sockaddr *) &addr_in,
00160 sizeof(addr_in));
00161 if (result < 0) throw CL_Error("CL_Socket::send failed");
00162
00163 if (impl->write) impl->write->start_listen();
00164 return result;
00165 }
00166
00167 int CL_Socket::recv(void *data, int size)
00168 {
00169 int result = ::recv(impl->sock, (char *) data, size, 0);
00170 if (result < 0) throw CL_Error("CL_Socket::recv failed");
00171
00172 if (impl->read) impl->read->start_listen();
00173 return result;
00174 }
00175
00176 int CL_Socket::recv(void *data, int size, CL_IPAddress &from)
00177 {
00178 sockaddr_in addr_in;
00179 memset(&addr_in, 0, sizeof(addr_in));
00180 addr_in.sin_family = AF_INET;
00181
00182 socklen_t addr_size = sizeof(addr_in);
00183
00184 int result = ::recvfrom(
00185 impl->sock,
00186 (char *) data,
00187 size,
00188 0,
00189 (sockaddr *) &addr_in,
00190 &addr_size);
00191 if (result < 0) throw CL_Error("CL_Socket::recv failed");
00192
00193 if (impl->read) impl->read->start_listen();
00194 from = CL_Socket_Generic::create_ip_address(addr_in);
00195 return result;
00196 }
00197
00198 void CL_Socket::connect(const CL_IPAddress &address)
00199 {
00200 sockaddr_in addr_in = CL_Socket_Generic::create_sockaddr_in(address);
00201 int result = ::connect(impl->sock, (sockaddr *) &addr_in, sizeof(addr_in));
00202 if (result < 0) throw CL_Error("CL_Socket::connect failed");
00203 if (impl->read) impl->read->start_listen();
00204 if (impl->exception) impl->exception->start_listen();
00205 }
00206
00207 void CL_Socket::shutdown(ShutdownHow how)
00208 {
00209 int in_how = 0;
00210 switch (how)
00211 {
00212 case shutdown_receive: in_how = 0; break;
00213 case shutdown_send: in_how = 1; break;
00214 }
00215
00216 int result = ::shutdown(impl->sock, in_how);
00217 if (result < 0) throw CL_Error("CL_Socket::shutdown failed");
00218 }
00219
00220 void CL_Socket::bind(const CL_IPAddress &address)
00221 {
00222 sockaddr_in addr_in = CL_Socket_Generic::create_sockaddr_in(address);
00223 int result = ::bind(impl->sock, (const sockaddr *) &addr_in, sizeof(addr_in));
00224 if (result < 0) throw CL_Error("CL_Socket::bind failed");
00225 }
00226
00227 void CL_Socket::listen(int backlog)
00228 {
00229 int result = ::listen(impl->sock, backlog);
00230 if (result < 0) throw CL_Error("CL_Socket::listen failed");
00231 }
00232
00233 CL_Socket CL_Socket::accept()
00234 {
00235 int new_sock = ::accept(impl->sock, NULL, NULL);
00236 if (new_sock == INVALID_SOCKET) throw CL_Error("CL_Socket::accept failed");
00237 if (impl->read) impl->read->start_listen();
00238 return CL_Socket(new_sock);
00239 }
00240
00242
00243
00244 CL_Socket::CL_Socket(CL_Socket_Generic *impl)
00245 : impl(impl)
00246 {
00247 impl->add_ref();
00248 }