00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ntcpsocket.h"
00023
00024 NTcpSocket::NTcpSocket(void)
00025 : NAbstractSocket(),
00026 m_sock(INVALID_SOCKET)
00027 {
00028 init();
00029 }
00030
00031
00032 NTcpSocket::NTcpSocket(NHostAddress &host)
00033 : NAbstractSocket(host),
00034 m_sock(INVALID_SOCKET)
00035 {
00036 init();
00037 }
00038
00039
00040 NTcpSocket::NTcpSocket(const NString &host, nuint16 port)
00041 : NAbstractSocket(host, port),
00042 m_sock(INVALID_SOCKET)
00043 {
00044 init();
00045 }
00046
00047 NTcpSocket::NTcpSocket(nuint16 timeout, nint32 sock)
00048 : NAbstractSocket(),
00049 m_addr(),
00050 m_sock(sock)
00051 {
00052 init();
00053 setTimeout(timeout);
00054 try {
00055 NDebug::print() << "Creating structures";
00056 m_addr = new struct addrinfo;
00057 NDebug::print() << "Zeroing";
00058 memset(m_addr, 0, sizeof(struct addrinfo));
00059
00060 m_addr->ai_addr = new struct sockaddr;
00061 memset(m_addr->ai_addr, 0, sizeof(struct sockaddr));
00062
00063 NDebug::print() << "Done zeroing";
00064 }
00065 catch (std::bad_alloc &) {
00066 if (m_addr && m_addr->ai_addr) {
00067 delete m_addr->ai_addr;
00068 }
00069
00070 delete m_addr;
00071 throw;
00072 }
00073
00074 NDebug::print() << "Setting peer address";
00075 m_host = peerAddress();
00076 setPort(peerPort());
00077 }
00078
00079
00080 NTcpSocket::~NTcpSocket(void) {
00081 WSACleanup();
00082 }
00083
00084
00085 void NTcpSocket::init(void) {
00086 WORD version;
00087 WSADATA wsaData;
00088
00089 memset(&m_host, 0, sizeof(m_host));
00090
00091 version = MAKEWORD(2 , 2);
00092
00093 if (WSAStartup(version, &wsaData) != 0) {
00094 throw NNetworkException("Unable to initialize winsock", "",
00095 NException::NETWORK, NNetworkException::SOCKET_INIT_FAILED);
00096 }
00097
00098 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
00099 WSACleanup();
00100 throw NNetworkException("Incorrect Winsock version", "",
00101 NException::NETWORK, NNetworkException::SOCKET_INIT_FAILED);
00102 }
00103
00104
00105 }
00106
00107
00108 void NTcpSocket::setPort(nint16 port) {
00109 NAbstractSocket::setPort(port);
00110 }
00111
00112
00113 void NTcpSocket::setSocketOptions(nint32 opt) {
00114
00115 }
00116
00117
00118 void NTcpSocket::throwSocketError(int err) const {
00119 NString msg;
00120
00121 switch (err) {
00122 case WSANOTINITIALISED: {
00123 msg = "Winsock was not initialized";
00124 break;
00125 }
00126 case WSAENETDOWN: {
00127 msg = "The network subsystem is down";
00128 break;
00129 }
00130 case WSAEAFNOSUPPORT: {
00131 msg = "Address family not supported";
00132 break;
00133 }
00134 case WSAEINPROGRESS: {
00135 msg = "A blocking winsock call is in progress";
00136 break;
00137 }
00138 case WSAEMFILE: {
00139 msg = "No more socket descriptors available";
00140 break;
00141 }
00142 case WSAENOBUFS: {
00143 msg = "No buffer space is available";
00144 break;
00145 }
00146 case WSAEPROTONOSUPPORT: {
00147 msg = "Protocol not supported";
00148 break;
00149 }
00150 case WSAEPROTOTYPE: {
00151 msg = "The specified protocol is incorrect";
00152 break;
00153 }
00154 case WSAESOCKTNOSUPPORT: {
00155 msg = "The specified socket type is incorrect";
00156 break;
00157 }
00158 case WSATRY_AGAIN: {
00159 msg = "Temporary failure in name resolution";
00160 break;
00161 }
00162 case WSAEINVAL: {
00163 msg = "Invalid value";
00164 break;
00165 }
00166 case WSANO_RECOVERY: {
00167 msg = "Nonrecoverable error in name resolution";
00168 break;
00169 }
00170 case WSA_NOT_ENOUGH_MEMORY: {
00171 msg = "Not enough memory";
00172 break;
00173 }
00174 case WSAHOST_NOT_FOUND: {
00175 msg = "Host not found";
00176 break;
00177 }
00178 case WSATYPE_NOT_FOUND: {
00179 msg = "Unsupported service type";
00180 break;
00181 }
00182 default: {
00183 msg = "Unhandled exception";
00184 break;
00185 }
00186 }
00187
00188 throw NNetworkException(msg, m_host.toString(), NException::NETWORK,
00189 NNetworkException::SOCKET_INIT_FAILED);
00190 }
00191
00192
00193 void NTcpSocket::open(void) {
00194 NString port;
00195 struct addrinfo hints;
00196 int ret = 0;
00197
00198 if (m_sock != INVALID_SOCKET) {
00199 return;
00200 }
00201
00202 memset(&hints, 0, sizeof(hints));
00203 hints.ai_family = AF_INET;
00204 hints.ai_socktype = SOCK_STREAM;
00205 hints.ai_protocol = IPPROTO_TCP;
00206
00207 port = NString::number(m_port);
00208
00209 if (m_host.isNull()) {
00210 ret = getaddrinfo(NULL, port.toChar(), &hints, &m_addr);
00211 }
00212 else {
00213 ret = getaddrinfo(m_host.toString().toChar(), port.toChar(), &hints, &m_addr);
00214 }
00215
00216 if (ret != 0) {
00217 NDebug::print() << "Getaddrinfo error!";
00218 throwSocketError(WSAGetLastError());
00219 }
00220
00221 m_sock = socket(m_addr->ai_family, m_addr->ai_socktype, m_addr->ai_protocol);
00222 if (m_sock == INVALID_SOCKET) {
00223 NDebug::print() << "socket() error!";
00224 throwSocketError(WSAGetLastError());
00225 }
00226 }
00227
00228
00229 void NTcpSocket::closeDevice(void) {
00230 disconnectFromHost();
00231 }
00232
00233
00234 void NTcpSocket::disconnectFromHost(void) {
00235 if (m_sock > 0) {
00236 closesocket(m_sock);
00237 m_sock = 0;
00238 }
00239 }
00240
00241
00242
00243 void NTcpSocket::connectToHost(void) {
00244 int ret = 0;
00245
00246 ret = connect(m_sock, m_addr->ai_addr, (int) m_addr->ai_addrlen);
00247 if (ret == SOCKET_ERROR) {
00248 NString msg = "Unable to connect to ";
00249 disconnectFromHost();
00250
00251 msg += m_host.toString() + NSTR(":") + NString::number(m_port);
00252 throw NNetworkException(msg, m_host.toString(), NException::NETWORK,
00253 NNetworkException::CONNECTION_FAILED);
00254 }
00255 }
00256
00257
00258 void NTcpSocket::execBind(void) {
00259 if (bind(m_sock, m_addr->ai_addr, (int)m_addr->ai_addrlen) == SOCKET_ERROR) {
00260 throwSocketError(WSAGetLastError());
00261 }
00262 }
00263
00264
00265 void NTcpSocket::execListen(void) {
00266 execBind();
00267 if (listen(m_sock, m_maxPendingConn) == SOCKET_ERROR) {
00268 disconnectFromHost();
00269 throw NNetworkException("Unable to listen", "",
00270 NException::NETWORK, NNetworkException::SOCKET_INIT_FAILED);
00271 }
00272 }
00273
00274
00275 NTcpSocket *NTcpSocket::waitForConnected(void) {
00276 SOCKET client = INVALID_SOCKET;
00277 NTcpSocket *ret = NULL;
00278
00279 NDebug::print() << "Accepting ... ";
00280 client = accept(m_sock, NULL, NULL);
00281 if (client == INVALID_SOCKET) {
00282 NDebug::print() << "Unable to accept ...";
00283 throwSocketError(WSAGetLastError());
00284 }
00285
00286 NDebug::print() << "Accepted";
00287 ret = new NTcpSocket(m_timeout, client);
00288 ret->setTimeout(m_timeout);
00289
00290 return ret;
00291 }
00292
00293 NHostAddress NTcpSocket::peerAddress(void) const {
00294 NHostAddress addr;
00295 int len = 0;
00296
00297 getpeername(m_sock, m_addr->ai_addr, &len);
00298 addr.setAddress(m_addr->ai_addr);
00299
00300 return addr;
00301 }
00302
00303
00304 NString NTcpSocket::peerName(void) const {
00305 return peerAddress().toString();
00306 }
00307
00308
00309 nuint16 NTcpSocket::peerPort(void) const {
00310 struct sockaddr_in *tmp;
00311
00312 tmp = reinterpret_cast<sockaddr_in *>(m_addr->ai_addr);
00313 return ntohs(tmp->sin_port);
00314 }
00315
00316
00317
00318 nint32 NTcpSocket::read(NDataStream *buffer) {
00319 nint32 bread = 0;
00320 fd_set fd;
00321 timeval timeout;
00322 nint32 sel = 0;
00323 socklen_t len = 0;
00324 nint32 numRead = -1;
00325 char tmp[2048];
00326
00327 FD_ZERO(&fd);
00328 FD_SET(m_sock, &fd);
00329
00330 timeout.tv_sec = m_timeout;
00331 timeout.tv_usec = 0;
00332
00333 sel = select(m_sock + 1, &fd, NULL, NULL, &timeout);
00334 if (sel < 0) {
00335 throw NNetworkException(nerror(errno), m_host.toString(),
00336 NException::NETWORK, NNetworkException::SOCK_ERROR);
00337 }
00338
00339 if (sel == 0) {
00340
00341 return 0;
00342 }
00343
00344 *buffer = "";
00345 do {
00346 memset(tmp, 0, sizeof(tmp));
00347
00348 numRead = recvfrom(m_sock, tmp, sizeof(tmp), 0, m_addr->ai_addr,
00349 &len);
00350
00351 if (numRead < 0) {
00352 NDebug::print() << "I did not received an orderly shutdown: "
00353 << WSAGetLastError();;
00354 return -1;
00355 }
00356 else {
00357
00358
00359 if (sel == 1 && numRead == 0 && bread == 0) {
00360 return -1;
00361 }
00362 }
00363
00364 bread += numRead;
00365 buffer->append(tmp, numRead);
00366 } while (numRead > 0);
00367
00368 return bread;
00369 }
00370
00371
00372 nint32 NTcpSocket::read(NDataStream *buffer, nuint32 bytes) {
00373 nuint32 bread = 0;
00374 fd_set fd;
00375 timeval timeout;
00376 nint32 sel = 0;
00377 socklen_t len = 0;
00378 nint32 numRead = -1;
00379 char tmp[1];
00380
00381 FD_ZERO(&fd);
00382 FD_SET(m_sock, &fd);
00383
00384 timeout.tv_sec = m_timeout;
00385 timeout.tv_usec = 0;
00386
00387 sel = select(m_sock + 1, &fd, NULL, NULL, &timeout);
00388 if (sel < 0) {
00389 throw NNetworkException(nerror(errno), m_host.toString(),
00390 NException::NETWORK, NNetworkException::SOCK_ERROR);
00391 }
00392
00393 if (sel == 0) {
00394
00395 return 0;
00396 }
00397
00398 *buffer = "";
00399 do {
00400 memset(tmp, 0, sizeof(tmp));
00401
00402 numRead = recvfrom(m_sock, tmp, 1, 0, m_addr->ai_addr, &len);
00403
00404 if (numRead < 0) {
00405 NDebug::print() << "I did not received an orderly shutdown: "
00406 << WSAGetLastError();;
00407 return -1;
00408 }
00409 else {
00410
00411
00412 if (sel == 1 && numRead == 0 && bread == 0) {
00413 return -1;
00414 }
00415 }
00416
00417 bread += numRead;
00418 buffer->append(tmp, numRead);
00419 } while (numRead > 0 && bread < bytes);
00420
00421 return bread;
00422 }
00423
00424
00425 nint32 NTcpSocket::readLine(NDataStream *buffer) {
00426 nint32 bread = 0;
00427 fd_set fd;
00428 timeval timeout;
00429 nint32 sel = 0;
00430 socklen_t len = 0;
00431 nint32 numRead = -1;
00432 char tmp[1];
00433
00434 FD_ZERO(&fd);
00435 FD_SET(m_sock, &fd);
00436
00437 timeout.tv_sec = m_timeout;
00438 timeout.tv_usec = 0;
00439
00440 sel = select(m_sock + 1, &fd, NULL, NULL, &timeout);
00441 if (sel == SOCKET_ERROR) {
00442 throwSocketError(WSAGetLastError());
00443 }
00444
00445 if (sel == 0) {
00446
00447 return -1;
00448 }
00449
00450 *buffer = "";
00451 do {
00452 memset(tmp, 0, sizeof(tmp));
00453
00454 numRead = recvfrom(m_sock, tmp, sizeof(tmp), 0, m_addr->ai_addr, &len);
00455 if (numRead < 0) {
00456 NDebug::print() << "I did not received an orderly shutdown: "
00457 << WSAGetLastError();;
00458 return -1;
00459 }
00460 else {
00461
00462
00463 if (sel == 1 && numRead == 0 && bread == 0) {
00464 return -1;
00465 }
00466 }
00467
00468 bread += numRead;
00469 buffer->append(tmp, numRead);
00470 if (tmp[0] == '\n' || tmp[0] == '\0') {
00471 break;
00472 }
00473 } while (numRead > 0);
00474
00475 return bread;
00476 }
00477
00478
00479 nint32 NTcpSocket::write(const NDataStream &data, nuint32 bytes) {
00480 if (bytes == 0) {
00481 return send(m_sock, static_cast<const char *>(data.data()), data.size(), 0);
00482 }
00483
00484 return send(m_sock, static_cast<const char *>(data.data()), bytes, 0);
00485 }
00486
00487
00488 nint32 NTcpSocket::writeLine(const NDataStream &data, nuint32 bytes) {
00489 NDataStream tmp = data;
00490
00491 tmp += "\r\n";
00492
00493 if (bytes == 0) {
00494 return send(m_sock, static_cast<const char *>(tmp.data()), tmp.size() + 2, 0);
00495 }
00496
00497 return send(m_sock, static_cast<const char *>(tmp.data()), bytes, 0);
00498 }