/* * */ #include #include /* close() */ #include #include /* memset() */ #include #include "UDPTCPNetwork.h" TCP::~TCP() { Close(); } TCP::TCP() { sock = 0; writecnt = 0; readcnt = 0; islisten = 0; }; TCP::TCP(int s) { TCP(); sock = s; // memset (&localaddr, 0x0, sizeof(localaddr)); // memset (&remoteaddr, 0x0, sizeof(remoteaddr)); writecnt = 0; readcnt = 0; islisten = 0; }; TCP::TCP(string h, string p) { TCP(); Connect (h,p); }; int TCP::Listen(int port) { char buffer[NET_BUFFERSIZE]; int err, i; struct addrinfo hints, *res, *rp; if (sock > 0) Close(); bzero (&hints, sizeof (struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo (NULL, itoa(buffer, port, 32), &hints, &res)) != 0) { return 0; } // // walk through all results until we could connect // for (rp = res; rp != NULL; rp = rp->ai_next) { sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sock == -1) continue; i = 1; if ((err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof (i))) != 0) { printf ("%s:%d setsockopt error\n", __FILE__, __LINE__); } if ((err = bind (sock, rp->ai_addr, rp->ai_addrlen)) < 0) { close (sock); sock = -1; continue; } if (listen (sock, 8) < 0) { // maximum of 8 connections at the time close (sock); sock = -1; continue; } break; } freeaddrinfo (res); if (rp == NULL) { sock = -1; return 0; } islisten = 1; return 1; }; TCP* TCP::Accept() { fd_set rfds; struct timeval tv; int retval, newsock, err, i; struct sockaddr_storage cli_addr; unsigned int cli_len = sizeof(cli_addr); char host[NET_BUFFERSIZE]; char port[NET_BUFFERSIZE]; TCP *tcp = NULL; if (sock <= 0) return NULL; FD_ZERO(&rfds); FD_SET(sock, &rfds); tv.tv_sec = 0; tv.tv_usec = 1000; retval = select (sock+1, &rfds, NULL, NULL, &tv); if (retval == -1 && errno == EINTR) { retval = 0; } else if (retval == -1) { return NULL; } else if (retval) { #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) newsock = accept (sock, (struct sockaddr *) &cli_addr, (int*) &cli_len); #else newsock = accept (sock, (struct sockaddr *) &cli_addr, &cli_len); #endif if (newsock < 0) return NULL; tcp = new TCP(); tcp->SetSocket(newsock, &cli_addr, cli_len); return tcp; } return NULL; } int TCP::Connect(string h, string p) { int i = 0; // memset (&localaddr, 0x0, sizeof(localaddr)); // memset (&remoteaddr, 0x0, sizeof(remoteaddr)); // i = dns_filladdr(h, p, AF_INET, &remoteaddr); // if (i == 0) return 0; remote_host = h; remote_port = p; return Connect(); }; int TCP::Connect(string hostport, int defaultport) { char buffer[32]; int pos = hostport.rfind(':', hostport.length()); if (pos == -1) { remote_port = itoa (buffer, defaultport, 32); remote_host = hostport; } else { remote_port = hostport.substr (pos+1, hostport.length() - pos); remote_host = hostport.substr (0, pos); } return Connect(); }; int TCP::Connect() { int err, s; struct addrinfo hints, *res, *rp; struct timeval timeout; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6 hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = 0; err = getaddrinfo(remote_host.c_str(), remote_port.c_str(), &hints, &res); if (err != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); return 0; } // // walk through all results until we could connect // for (rp = res; rp != NULL; rp = rp->ai_next) { s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); // setup timeout to max 2 secs timeout.tv_sec = 2; timeout.tv_usec = 0; setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); if (s == -1) continue; if (connect(s, rp->ai_addr, rp->ai_addrlen) != -1) { sock = s; break; } close(s); } freeaddrinfo(res); // // connect not successfull // if (rp == NULL) return 0; writecnt = 0; readcnt = 0; return 1; }; long int TCP::ReadPop (char *buffer, long int pktlen, long int bufferlen) { memmove (buffer, buffer+pktlen, bufferlen-pktlen); return bufferlen-pktlen; } long int TCP::Read(char *buffer, long int len) { long int len_ = len; if (sock <= 0) return -2; len_ = read (sock, (void*)buffer, len); // printf ("read: "); debug_mem(buffer, len_); if (len_ < 0 && errno == EAGAIN) len_ = 0; else if (len_ < 0 && errno != EAGAIN) { // fprintf (stderr, "%s ERROR:%s\n", __FUNCTION__, strerror (errno)); len_ = -2; } else if (len_ == 0) len_ = -1; if (len_ < 0) Close(); readcnt += len_; return len_; }; long int TCP::ReadTimeout(char *buffer, long int len, int timeout) { int data = IsData (timeout); if (data > 0) return Read (buffer, len); else if (data < 0) return -1; else return 0; }; ////////////////////////////////////////////////////////// // // write data, generate no signal if some error occures long int TCP::Write(char *buffer, long int len) { int i; int to = NET_MAX_RETRY; if (sock <= 0) return -1; do { i = send (sock, buffer, len, MSG_NOSIGNAL); } while (i == -1 && (to--) > 0 && errno == EINTR); if (i < 0) Close (); writecnt += i; return i; }; void TCP::Close() { if (sock > 0) close (sock); sock = -1; islisten = false; }; void TCP::SetSocket(int s, struct sockaddr_storage *saddr, int saddrlen) { char host[NET_HOSTLEN]; char port[NET_PORTLEN]; int err; if (sock > 0) Close(); if (s > 0) { sock = s; if (saddr != NULL) { if ((err = getnameinfo ((struct sockaddr*) &saddr, saddrlen, host, NET_HOSTLEN, port, NET_PORTLEN, NI_NUMERICHOST | NI_NUMERICSERV)) == 0) { remote_host = host; remote_port = port; } } } else sock = -1; }; int TCP::IsConnected() { return (sock > 0); }; int TCP::IsData(int timeout) { fd_set sockset; struct timeval tval; if (sock <= 0) return -1; FD_ZERO (&sockset); FD_SET (sock, &sockset); tval.tv_sec = timeout / 1000; tval.tv_usec = (timeout % 1000); if ((select (sock + 1, &sockset, NULL, NULL, &tval)) != -1) { if (FD_ISSET (sock, &sockset)) return 1; return 0; } else { if (errno == EBADF) sock = -1; } return 0; }; int TCP::WebGetFile (string url, char *buffer, int maxsize) { char outdata[NET_BUFFERSIZE]; char indata[NET_BUFFERSIZE]; char host[NET_HOSTLEN]; char port[NET_PORTLEN]; int breakup, len, head, i, buffpos = 0; if (!IsConnected()) { strncpy (host, WebGetURLHost (url).c_str(), NET_HOSTLEN); strncpy (port, WebGetURLPort (url).c_str(), NET_PORTLEN); Connect (host, port); } if (!IsConnected()) return -1; // send http request snprintf (outdata, NET_BUFFERSIZE, "GET %s HTTP/1.0\nUser-Agent: tcpclient \nHost: %s\n\n", WebGetURLFile (url).c_str(), host); Write (outdata, strlen (outdata)); // wait for data start i = breakup = 0; head = 1; while (!breakup && head && (len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) >= 0) { indata[len] = 0; while (i < len -4 && head && !breakup) { if (indata[i] == 0x0d && indata [i+1] == 0x0a && indata [i+2] == 0x0d && indata [i+3] == 0x0a) { head = 0; i = i + 4; buffpos = len-i; if (buffpos > maxsize) buffpos = maxsize; memcpy (buffer, indata+i, buffpos); } else if (strncmp (indata+i, "Content-Length:", 15) == 0) { i = i + 16; } else if (strncmp (indata+i, "403 ", 4) == 0) breakup = 1; else i++; } } // read data while (!breakup && (len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) >= 0) { i = len; if (i > maxsize-buffpos) i = maxsize-buffpos; if (i > 0) { memcpy (buffer+buffpos, indata, i); buffpos += i; } } return buffpos; }; const string TCP::WebGetURLHost (string url) { string result; int posSServPort = 7; // begin server:port int posEServPort = 0; // end Server:Port int posPort = -1; // port Position posEServPort = url.find("/", 7); result = url.substr (posSServPort, posEServPort-posSServPort); posPort = result.find(":"); if (posPort > 0) result = url.substr (posSServPort, posPort); return result; }; const string TCP::WebGetURLPort (string url) { string result; int posSServPort = 7; // begin server:port int posEServPort = 0; // end Server:Port int posPort = -1; // port Position posEServPort = url.find("/", 7); result = url.substr (posSServPort, posEServPort-posSServPort); posPort = result.find(":"); if (posPort > 0) result = result.substr (posPort+1); else result = "80"; return result; }; const string TCP::WebGetURLFile (string url) { string result; int posEServPort = 0; // end Server:Port posEServPort = url.find("/", 7); result = url.substr (posEServPort); return result; }; const string TCP::GetRemoteAddr() { string ret; struct sockaddr addr; socklen_t addrlen = sizeof (struct sockaddr); char host[256] = ""; char port[256] = ""; if (getpeername (sock, &addr, &addrlen) == -1) { printf ("getpeername error: %s\n", strerror(errno)); return ret; } if (getnameinfo (&addr, addrlen, host, 255, port, 255, 0) == -1) { printf ("getnameinfo error: %s\n", strerror(errno)); return ret; } ret = (string)host + ":" + (string)port; return ret; }; const string TCP::GetLocalAddr() { string ret; return ret; };