00001 #include "headers.h"
00002
00007
00008
00009 TcpConnection::TcpConnection()
00010 {
00011 m_stream = OS_SPEC_INVALID_SOCKET;
00012 }
00013
00014
00015 TcpConnection::TcpConnection(SocketAddress socketAddress)
00016 {
00017 m_stream = OS_SPEC_INVALID_SOCKET;
00018 m_socketAddress = socketAddress;
00019 }
00020
00021
00022 TcpConnection::TcpConnection(IpAddress ipAddr, unsigned short port)
00023 {
00024 m_stream = OS_SPEC_INVALID_SOCKET;
00025 m_socketAddress = SocketAddress(ipAddr, port);
00026 }
00027
00028
00032 TcpConnection::TcpConnection(unsigned short port)
00033 {
00034 m_stream = OS_SPEC_INVALID_SOCKET;
00035 m_socketAddress = SocketAddress(IpAddress((unsigned long)INADDR_ANY), port);
00036 }
00037
00038
00042 TcpConnection::~TcpConnection() {
00043 close();
00044 }
00045
00046
00047 ConnectionInterface::ObjectType
00048 TcpConnection::getConnectionType() {
00049 return TCP_CONNECTION;
00050 }
00051
00052
00057 void
00058 TcpConnection::setSocketOptions() {
00059
00060 int turnOn = 1;
00061 int err = setsockopt(m_stream, IPPROTO_TCP, TCP_NODELAY, (const char*)&turnOn, sizeof(int));
00062 if (err == OS_SPEC_SOCKET_ERROR) {
00063 debug(DEBUG_CONN, "Error setting TCP_NODELAY");
00064 }
00065
00066
00067 err = setsockopt(m_stream, SOL_SOCKET, SO_KEEPALIVE, (const char*)&turnOn, sizeof(int));
00068 if (err == OS_SPEC_SOCKET_ERROR) {
00069 debug(DEBUG_CONN, "Error setting socket Keep-Alive");
00070 }
00071 }
00072
00073
00078 int
00079 TcpConnection::connect()
00080 {
00081 if(!isConnected()) {
00082 m_stream = socket(AF_INET, SOCK_STREAM, 0);
00083
00084
00085 if (m_stream == OS_SPEC_INVALID_SOCKET) {
00086 debug(DEBUG_CONN, "Socket error, windows return code:\n%s", printWsaErrorCode());
00087 return 0;
00088 }
00089
00090 setSocketOptions();
00091
00092 debug(DEBUG_CONN, "Trying to connect to %s, port %d",
00093 m_socketAddress.getIpAddress().toCStr(),
00094 m_socketAddress.getPort());
00095
00096 if (::connect(m_stream, (struct sockaddr *) m_socketAddress.getSockAddrStruct(), sizeof(struct sockaddr_in)) != 0)
00097 {
00098 debug(DEBUG_CONN, "connect error");
00099 debug(DEBUG_CONN, "%s", printWsaErrorCode());
00100 OS_SPEC_SOCKETCLOSE(m_stream);
00101 m_stream = OS_SPEC_INVALID_SOCKET;
00102 return 0;
00103 }
00104
00105 debug(DEBUG_CONN, "Connected to %s, port %d",
00106 m_socketAddress.getIpAddress().toCStr(),
00107 m_socketAddress.getPort());
00108
00109 fireEvent(CONNECTION_OPENED);
00110
00111 debug(DEBUG_CONN, "connect() successful");
00112 return 1;
00113 }
00114 else {
00115 debug(DEBUG_CONN, "Already connected");
00116 }
00117 return 0;
00118 }
00119
00120
00131 int
00132 TcpConnection::read(unsigned char* buffer, int bufferSize, int amountToRead)
00133 {
00134 if (!isConnected()) {
00135 debug(DEBUG_CONN, "trying to read from a Connection that isnt connected!");
00136 return -1;
00137 }
00138
00139 if (amountToRead > bufferSize) {
00140 debug(DEBUG_CONN, "ERROR: (amountToRead > bufferSize)");
00141 return -1;
00142 }
00143
00144
00145
00146 int bytesRead = 0;
00147 int totalBytesRead = 0;
00148
00149 if (amountToRead == 0) {
00150 totalBytesRead = recv(getStream(), (char*)buffer, bufferSize, 0);
00151
00152 if (totalBytesRead <= 0) {
00153 debug(DEBUG_CONN, "socket read error: %s", strerror(errno));
00154 debug(DEBUG_CONN, "%s", printWsaErrorCode());
00155 }
00156 }
00157 else {
00158 while ((bytesRead >= 0) && (totalBytesRead != amountToRead)) {
00159 bytesRead = recv(getStream(), (char*)buffer + totalBytesRead, amountToRead - totalBytesRead, 0);
00160
00161 if (bytesRead <= 0) {
00162 debug(DEBUG_CONN, "socket read error: %s", strerror(errno));
00163 debug(DEBUG_CONN, "%s", printWsaErrorCode());
00164
00165 totalBytesRead = bytesRead;
00166 break;
00167 }
00168 totalBytesRead += bytesRead;
00169 }
00170 }
00171
00172 debug(DEBUG_CONN, "read data: %d bytes", totalBytesRead);
00173 return totalBytesRead;
00174 }
00175
00176
00181 int
00182 TcpConnection::write(unsigned char* buffer, int amountToWrite) {
00183 int bytesWritten = 0;
00184 int sendResult = 0;
00185
00186 do {
00187 sendResult = send(m_stream, (const char*)&buffer[bytesWritten], amountToWrite - bytesWritten, 0);
00188 bytesWritten += sendResult;
00189 } while ((bytesWritten != amountToWrite) && (sendResult > 0));
00190
00191 if (bytesWritten != amountToWrite) {
00192 debug(DEBUG_CONN, "Error - did not send all data");
00193 }
00194
00195 if (sendResult < 0) {
00196 printWsaErrorCode();
00197 return sendResult;
00198 }
00199 return bytesWritten;
00200 }
00201
00202
00211 int
00212 TcpConnection::listen() {
00213 m_stream = createListeningSocket(m_socketAddress);
00214 if (m_stream != OS_SPEC_INVALID_SOCKET) {
00215 return 1;
00216 }
00217 else {
00218 return 0;
00219 }
00220 }
00221
00222
00228 OS_SPEC_SOCKET_TYPE
00229 TcpConnection::createListeningSocket(SocketAddress socketAddress) {
00230 OS_SPEC_SOCKET_TYPE stream;
00231 stream = socket(AF_INET, SOCK_STREAM, 0);
00232
00233 if (stream == OS_SPEC_INVALID_SOCKET) {
00234 debug(DEBUG_ERR, "socket creation error");
00235 debug(DEBUG_ERR, "%s", printWsaErrorCode());
00236 }
00237 else {
00238 if ((0 != bind(stream,
00239 (struct sockaddr *)socketAddress.getSockAddrStruct(),
00240 *(socketAddress.getSockAddrStructLen()))))
00241 {
00242 debug(DEBUG_ERR, "bind error: IP address: %s", socketAddress.toCStr());
00243 debug(DEBUG_ERR, "%s", printWsaErrorCode());
00244 stream = OS_SPEC_INVALID_SOCKET;
00245 }
00246 else {
00247
00248 (void) ::listen(stream, MAX_CONNECTIONS + 5);
00249 debug(DEBUG_ERR, "Socket stream fd=%d listening on address %s",
00250 stream, socketAddress.toCStr());
00251 }
00252 }
00253 return stream;
00254 }
00255
00256
00265 ConnectionInterface*
00266 TcpConnection::accept()
00267 {
00268 int n = 0;
00269 int newfd = 0;
00270 int i = 0;
00271 int acceptHighestFd = 0;
00272 TcpConnection* newConnection = NULL;
00273 fd_set listenSockets;
00274
00275
00276
00277
00278
00279 FD_ZERO(&listenSockets);
00280
00281
00282 setSocketOptions();
00283 int stream = m_stream;
00284 if (stream != OS_SPEC_INVALID_SOCKET) {
00285 OS_SPEC_FD_SET(stream, &listenSockets);
00286 if (stream > acceptHighestFd) {
00287 acceptHighestFd = stream;
00288 }
00289 }
00290 else {
00291 debug(DEBUG_CONN, "ERROR: stream is bad!");
00292 return NULL;
00293 }
00294
00295
00296 n = select(acceptHighestFd + 1, &listenSockets, NULL, NULL, NULL);
00297 debug(DEBUG_CONN, "select: returned %d", n);
00298
00299
00300 #ifdef WIN32
00301 if (n == INVALID_SOCKET) {
00302 #else
00303 if (n <= 0) {
00304 #endif
00305 debug(DEBUG_CONN, "select error: %s\n Highest fd: %d", printWsaErrorCode(), acceptHighestFd);
00306 return NULL;
00307 }
00308
00309
00310
00311
00312 if(OS_SPEC_FD_ISSET(m_stream, &listenSockets))
00313 {
00314
00315 SocketAddress socketAddress;
00316 if ((newfd = ::accept(m_stream,
00317 (struct sockaddr *) socketAddress.getSockAddrStruct(),
00318 socketAddress.getSockAddrStructLen())) < 0) {
00319 debug(DEBUG_CONN, "accept() error, port#%d: %s", i, strerror(errno));
00320 return NULL;
00321 }
00322
00323 socketAddress.setSocketAddress(socketAddress.getSockAddrStruct());
00324
00325
00326 debug(DEBUG_CONN, "new incoming connection: %s", socketAddress.toCStr());
00327
00328
00329 newConnection = new TcpConnection(socketAddress);
00330 MEMCHECK(newConnection);
00331 newConnection->setStream(newfd);
00332 }
00333 else {
00334 debug(DEBUG_CONN, "Select returned, but no sockets flagged");
00335 }
00336 return newConnection;
00337 }
00338
00339
00343 void
00344 TcpConnection::close() {
00345 if(isConnected()) {
00346 debug(DEBUG_CONN, "Closing connection");
00347 if (m_stream != OS_SPEC_INVALID_SOCKET) {
00348 OS_SPEC_SOCKETCLOSE(m_stream);
00349 m_stream = OS_SPEC_INVALID_SOCKET;
00350 }
00351 debug(DEBUG_CONN, "connection closed");
00352
00353 fireEvent(ConnectionInterface::CONNECTION_CLOSED);
00354 }
00355 }
00356
00357
00361 bool
00362 TcpConnection::isConnected() {
00363 if (m_stream != OS_SPEC_INVALID_SOCKET) {
00364 return true;
00365 }
00366 else {
00367 return false;
00368 }
00369 }
00370
00371
00376 bool
00377 TcpConnection::isConnectedTo(IpAddress ipAddr) {
00378 if ((m_socketAddress.getIpAddress().equals(ipAddr)) && isConnected()) {
00379 return true;
00380 }
00381 else {
00382 return false;
00383 }
00384 }
00385
00386
00387 SocketAddress*
00388 TcpConnection::getSocketAddress() {
00389 return &m_socketAddress;
00390 }
00391
00392
00393 void
00394 TcpConnection::setSocketAddress(SocketAddress* socketAddress) {
00395 m_socketAddress = *socketAddress;
00396 }
00397
00398
00402 int
00403 TcpConnection::getStream() {
00404 return m_stream;
00405 }
00406
00407
00411 void
00412 TcpConnection::setStream(int stream) {
00413 if (!isConnected()) {
00414 m_stream = stream;
00415 }
00416 }
00417
00418
00419 void
00420 TcpConnection::toStream(std::ostream& out) {
00421 out << m_socketAddress;
00422 }
00423