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 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 #include "JSocket.h"
00049 
00050 
00051 #ifdef WIN32
00052         #include "win32/JSocket_Win32.cpp"
00053 #else
00054         #include "linux/JSocket_Linux.cpp"
00055 #endif
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 namespace cmlabs {
00064 
00065 
00066 
00067 
00068 
00069 JSocket::JSocket(JString addr, int portnumber, JString protocolname) {
00070         resetIOCounts();
00071         strcpy(charBuffer, "");
00072         isTerminating = false;
00073         currentUnsentBufferSize = 0;
00074         currentSentBufferSize = 0;
00075         currentUnreceivedBufferSize = 0;
00076         currentReceivedBufferSize = 0;
00077         charBufferCount = 0;
00078         charBuffer[0] = 0;
00079         location = TCPLocation(addr, portnumber, "");
00080         address = addr;
00081         port = portnumber;
00082         protocol = protocolname;
00083         lastErrorMessage = "";
00084 
00085         connected = false;
00086         lastErrorRecoverable = true;
00087         listening = false;
00088 
00089         ipnumber.a = 0;
00090         ipnumber.b = 0;
00091         ipnumber.c = 0;
00092         ipnumber.d = 0;
00093 
00094         setSocketNotValid();
00095 }
00096 
00097 JSocket::JSocket(const TCPLocation& loc, JString protocolname) {
00098         resetIOCounts();
00099         isTerminating = false;
00100         currentUnsentBufferSize = 0;
00101         currentSentBufferSize = 0;
00102         currentUnreceivedBufferSize = 0;
00103         currentReceivedBufferSize = 0;
00104         charBufferCount = 0;
00105         charBuffer[0] = 0;
00106         location = loc;
00107         address = loc.addr;
00108         port = loc.port;
00109         protocol = protocolname;
00110         lastErrorMessage = "";
00111 
00112         connected = false;
00113         lastErrorRecoverable = true;
00114         listening = false;
00115 
00116         ipnumber.a = loc.ipnumber.a;
00117         ipnumber.b = loc.ipnumber.b;
00118         ipnumber.c = loc.ipnumber.c;
00119         ipnumber.d = loc.ipnumber.d;
00120 
00121         setSocketNotValid();
00122 }
00123 
00124 
00125 JSocket::~JSocket() {
00126         isTerminating = true;
00127 
00128 
00129 
00130         terminate();
00131 
00132 
00133 }
00134 
00135 
00136 long JSocket::getSendBufferSize() {
00137         return SENDBUFFERSIZE;
00138 }
00139 long JSocket::getReadBufferSize() {
00140         return BUFFERSIZE;
00141 }
00142 
00143 bool JSocket::terminate() {
00144         return disconnectNow();
00145 }
00146 
00147 
00148 bool JSocket::isListening() {
00149         return listening;
00150 }
00151 
00152 bool JSocket::isLastErrorRecoverable() {
00153         return lastErrorRecoverable;
00154 }
00155 
00156 JString JSocket::getLastErrorMessage() {
00157         return lastErrorMessage;
00158 }
00159 
00160 int JSocket::flush() {
00161         int c = 0;
00162         readIntoBuffer();
00163         while (charBufferCount > 0) {
00164                 c += charBufferCount;
00165                 charBufferCount = 0;
00166                 readIntoBuffer();
00167         }
00168         strcpy(charBuffer, "Flushed!");
00169         return c;
00170 }
00171 
00172 
00173 int JSocket::read(char* buffer, int maxcount, long timeout) {
00174 
00175         int copyCount = 0;
00176         currentUnreceivedBufferSize = maxcount;
00177 
00178         
00179         if (this->charBufferCount < maxcount) {
00180                 waitForReadability(timeout);
00181                 if (readIntoBuffer() == -1) {
00182                         currentUnreceivedBufferSize = 0;
00183                         currentReceivedBufferSize = 0;
00184                         return -1;
00185                 }
00186         }
00187 
00188         if (charBufferCount == 0) {
00189                 currentUnreceivedBufferSize = 0;
00190                 currentReceivedBufferSize = 0;
00191                 return 0;
00192         }
00193         
00194         int c=0;
00195         while (maxcount > copyCount) {
00196 
00197                 if (maxcount >= copyCount + charBufferCount){
00198                         memcpy(buffer+copyCount, charBuffer, charBufferCount);
00199                         copyCount += charBufferCount;
00200                         charBufferCount = 0;
00201                 }
00202                 else {
00203                         int toRemainInBuffer = copyCount + charBufferCount - maxcount;
00204                         memcpy(buffer+copyCount, charBuffer, charBufferCount-toRemainInBuffer);
00205                         copyCount += charBufferCount-toRemainInBuffer;
00206 
00207 
00208 
00209                         
00210                                 memmove(charBuffer, charBuffer+charBufferCount-toRemainInBuffer, toRemainInBuffer);
00211                                 charBufferCount = toRemainInBuffer;
00212 
00213                 }
00214                 if (maxcount == copyCount) {
00215                         currentUnreceivedBufferSize = maxcount;
00216                         currentReceivedBufferSize = maxcount;
00217                         return copyCount;
00218                 }
00219 
00220                 if ((readIntoBuffer() == -1) || (charBufferCount <= 0)) {
00221                         waitForReadability(timeout);
00222                         if (readIntoBuffer() == -1) {
00223                                 printf("INCOMPLETE2!!!");
00224                                 currentUnreceivedBufferSize = copyCount;
00225                                 currentReceivedBufferSize = copyCount;
00226                                 return copyCount;
00227                         }
00228                 }
00229         }
00230         
00231         if (charBufferCount >= maxcount)
00232                 copyCount = maxcount;
00233         else
00234                 copyCount = charBufferCount;
00235 
00236         currentUnreceivedBufferSize = copyCount;
00237         currentReceivedBufferSize = copyCount;
00238 
00239         int newCharBufferCount = charBufferCount - copyCount;
00240 
00241         memcpy(buffer, charBuffer, copyCount);
00242 
00243         if (newCharBufferCount == 0) {
00244                 charBufferCount = 0;
00245         }
00246         else if (newCharBufferCount > 0) {
00247         
00248                 memmove(charBuffer, charBuffer+copyCount, newCharBufferCount);
00249                 charBufferCount = newCharBufferCount;
00250         }
00251         
00252         return copyCount;
00253 }
00254 
00255 
00256 JString JSocket::readString(int count, long timeout) {
00257 
00258         JString text;
00259 
00260         if ( (currentUnreceivedBufferSize == 0) || (currentUnreceivedBufferSize == currentReceivedBufferSize) ) {
00261                 currentUnreceivedBufferSize = count;
00262                 currentReceivedBufferSize = 0;
00263         }
00264 
00265         if (count > BUFFERSIZE) {
00266                 currentUnreceivedBufferSize = count;
00267                 currentReceivedBufferSize = 0;
00268                 JString str;
00269                 text = readString(BUFFERSIZE, timeout);
00270                 if (text.length() == 0) return "";
00271                 int tcount = count - BUFFERSIZE;
00272                 while (tcount > BUFFERSIZE) {
00273                         currentReceivedBufferSize = count - tcount;
00274                         str = readString(BUFFERSIZE, timeout);
00275                         tcount -= BUFFERSIZE;
00276                         if (str.length() == 0) return text;
00277                         else text += str;
00278                 }
00279                 str = readString(tcount, timeout);
00280                 text += str;
00281                 currentReceivedBufferSize = count;
00282                 return text;
00283         }
00284 
00285         
00286         if (this->charBufferCount < count) {
00287                 waitForReadability(timeout);
00288                 readIntoBuffer();
00289         }
00290 
00291         int newCharBufferCount = charBufferCount - count;
00292 
00293 
00294         charBuffer[charBufferCount] = 0;
00295 
00296         if (newCharBufferCount == 0) {
00297                 text = charBuffer;
00298                 charBufferCount = 0;
00299         }
00300         else if (newCharBufferCount > 0) {
00301                 text = charBuffer;
00302                 text = text.substring(0, count);
00303         
00304                 memmove(charBuffer, charBuffer+count, newCharBufferCount);
00305                 charBufferCount = newCharBufferCount;
00306         }
00307 
00308         if ( (currentUnreceivedBufferSize == count) && (currentReceivedBufferSize == 0) ) {
00309                 currentUnreceivedBufferSize = newCharBufferCount;
00310                 currentReceivedBufferSize = newCharBufferCount;
00311         }
00312 
00313         return text;
00314 }
00315 
00316 JString JSocket::readln(long timeout) {
00317 
00318 
00319         JString str;
00320         JTime t;
00321         int m, n = -10;
00322         int count = 0;
00323         while ((JTime()-t < timeout) && (n < 0)) {
00324           
00325           count++;
00326 
00327                 waitForReadability(timeout - (JTime()-t));
00328                 if (charBufferCount >= BUFFERSIZE) {
00329                         charBuffer[charBufferCount] = 0;
00330                         stringBuffer += charBuffer;
00331                         
00332                         charBufferCount = 0;
00333                 }
00334 
00335                 
00336                 
00337                 if (readIntoBuffer() == -1) {
00338                         return "";
00339 
00340 
00341 
00342 
00343 
00344                 }
00345                 charBuffer[charBufferCount] = 0;
00346                 n = (int)(strchr(charBuffer, 10) - charBuffer);
00347                 if (n > charBufferCount) n = -1;
00348                 
00349         }
00350 
00351         if ((charBufferCount == 0) || (n < 0)) return "";
00352 
00353         
00354         m = (int)(strchr(charBuffer, 13) - charBuffer);
00355         
00356 
00357         
00358         charBuffer[n] = 0;
00359         str = charBuffer;
00360 
00361         JString text = stringBuffer;
00362 
00363         
00364         if ((m >= 0) && (m == n-1))
00365                 text += str.substring(0, m);
00366         
00367         else
00368                 text += str.substring(0, n);
00369 
00370         stringBuffer = "";
00371 
00372         int newCharBufferCount = charBufferCount-(n+1);
00373 
00374         memmove(charBuffer, charBuffer+n+1, newCharBufferCount);
00375         charBufferCount = newCharBufferCount;
00376 
00377         
00378         text.isCRTerminated = true;
00379 
00380         return text;
00381 }
00382 
00383 int JSocket::write(JString str) {
00384         return writeString(str);
00385 }
00386 
00387 int JSocket::write(char* ch, int len) {
00388         return writeBuffer(ch, len);
00389 }
00390 
00391 int JSocket::writeln(JString str) {
00392         char ch[3];
00393         ch[0] = 13;
00394         ch[1] = 10;
00395         ch[2] = 0;
00396 
00397         return writeString(str + ch);
00398 }
00399 
00400 
00401 
00402 JString JSocket::getLocalIPAddress() {
00403 
00404         if (localIPAddress.length() > 0)
00405                 return localIPAddress;
00406 
00407         int n;
00408         Collection addresses;
00409         
00410         Collection locals = getLocalIPAddresses();
00411 
00412         JString addr;
00413         for (n=0; n<locals.getCount(); n++) {
00414                 addr = locals.get(n);
00415                 if ( (addr.length() > 0) && (!addr.equalsIgnoreCase("127.0.0.1")) && (!addr.equalsIgnoreCase("0.0.0.0")) ) {
00416                         addresses.add(addr);
00417                 }
00418         }
00419 
00420         if (addresses.length() > 0) {
00421                 localIPAddress = addresses.getFirst();
00422         }
00423         else {
00424                 localIPAddress = "127.0.0.1";
00425         }
00426 
00427         return localIPAddress;
00428 }
00429 
00430 Collection JSocket::getLocalIPAddresses() {
00431 
00432         if (localIPAddresses.getCount() > 0)
00433                 return localIPAddresses;
00434 
00435         localIPAddresses.add("127.0.0.1");
00436 
00437         char szHostName[255];
00438 
00439 
00440         bool canAskHost = true;
00441         if( gethostname(szHostName, 255) != 0 ) {
00442                 #ifdef WIN32
00443                         int err = getLastOSErrorNumber();
00444                         if (err == WSANOTINITIALISED) {
00445                                 WSADATA info;
00446                                 if (WSAStartup(MAKEWORD(1,1), &info) != 0) {
00447                                         printf("Could not startup network...\n");
00448                                         return localIPAddresses;
00449                                 }
00450                                 else {
00451                                         if( gethostname(szHostName, 255) != 0 ) {
00452                                                 printf("Could not ask for local host name...\n");
00453                                                 canAskHost = false;
00454                                                 
00455                                         }
00456                                 }
00457                         }
00458                         else {
00459                                 printf("Could not ask for local host name...\n");
00460                                 canAskHost = false;
00461                                 
00462                         }
00463                 #else // WIN32
00464                         printf("Could not ask for local host name...\n");
00465                         canAskHost = false;
00466                         
00467                 #endif // WIN32
00468         }
00469 
00470 
00471         if (canAskHost) {
00472                 
00473                 struct hostent * pHost;
00474                 int i;
00475 
00476                 #ifdef WIN32
00477                         pHost = gethostbyname(szHostName);
00478                 #else // WIN32
00479 
00480                         #ifdef Darwin
00481 
00482                                 pHost = gethostbyname(szHostName);
00483                                 if (pHost == NULL) {
00484                                         
00485                                         return localIPAddresses;
00486                                 }
00487                                 else {}
00488                         #else // Darwin
00489 
00490                         pHost = new struct hostent;
00491                         char bf[2000];
00492                         int er;
00493                         int res = gethostbyname_r(szHostName, pHost, bf, 2000, &pHost, &er);
00494                         if ((er == 0) || (res != 0)) {
00495                                 if (DEBUGLEVEL(HEARTBEAT)) {
00496                                         printf("gethostbyname_r success: %s!!!\n", szHostName);
00497                                 }
00498                         }
00499                         else {
00500                                 if (er == ERANGE) {
00501                                         if (DEBUGLEVEL(KITCHENSINK)) {
00502                                                 printf("gethostbyname_r error %s: ERANGE\n", (char*) szHostName);
00503                                         }
00504                                         delete pHost;
00505                                         pHost = NULL;
00506                                 }
00507                                 else if (er == HOST_NOT_FOUND ) {
00508                                         if (DEBUGLEVEL(KITCHENSINK)) {
00509                                                 printf("gethostbyname_r error %s: HOST_NOT_FOUND \n", (char*) szHostName);
00510                                         }
00511                                         delete pHost;
00512                                         pHost = NULL;
00513                                 }
00514                                 else if (er == NO_ADDRESS ) {
00515                                         if (DEBUGLEVEL(KITCHENSINK)) {
00516                                                 printf("gethostbyname_r error %s: NO_ADDRESS \n", (char*) szHostName);
00517                                         }
00518                                         delete pHost;
00519                                         pHost = NULL;
00520                                 }
00521                                 else if (er == NO_DATA ) {
00522                                         if (DEBUGLEVEL(KITCHENSINK)) {
00523                                                 printf("gethostbyname_r error %s: NO_DATA \n", (char*) szHostName);
00524                                         }
00525                                         delete pHost;
00526                                         pHost = NULL;
00527                                 }
00528                                 else if (er == NO_RECOVERY ) {
00529                                         if (DEBUGLEVEL(KITCHENSINK)) {
00530                                                 printf("gethostbyname_r error %s: NO_RECOVERY \n", (char*) szHostName);
00531                                         }
00532                                         delete pHost;
00533                                         pHost = NULL;
00534                                 }
00535                                 else if (er == TRY_AGAIN ) {
00536                                         if (DEBUGLEVEL(KITCHENSINK)) {
00537                                                 printf("gethostbyname_r error %s: TRY_AGAIN \n", (char*) szHostName);
00538                                         }
00539                                         delete pHost;
00540                                         pHost = NULL;
00541                                 }
00542                                 else {
00543         
00544         
00545         
00546                                         
00547                                 }
00548                         }
00549 
00550                         #endif // Darwin
00551                 #endif // WIN32
00552 
00553                 JString str;
00554                 for( i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
00555                 {
00556                         int j;
00557                         str = "";       
00558                         for( j = 0; j < pHost->h_length; j++ )
00559                         {
00560                                 
00561                 
00562                                 if( j > 0 )
00563                                         str += ".";
00564                 
00565                                 str += JString((int)((unsigned char*)pHost->h_addr_list[i])[j]);
00566                                 
00567                         }
00568                         
00569                         if ( (str.length() > 0) && (!localIPAddresses.contains(str)) )
00570                                 localIPAddresses.add(str);
00571                 }
00572 
00573                 if (DEBUGLEVEL(HEARTBEAT))
00574                         printf("gethostbyname_r found %d IPs: %s\n", localIPAddresses.getCount(), (char*) localIPAddresses.printListLine(","));
00575 
00576                 #ifdef WIN32
00577                 #else // WIN32
00578                 #ifdef Darwin
00579                                 endhostent();
00580                 #else
00581                         delete pHost;
00582                 #endif // Darwin
00583                 #endif // WIN32
00584         }
00585 
00586         
00587         
00588 
00589                 
00590                 Dictionary dict = getLocalInterfaceAddresses();
00591                 JString addr;
00592                 for (int n=0; n<dict.getCount(); n++) {
00593                         addr = dict.get(n);
00594                         if ( (addr.length() > 0) && (!localIPAddresses.contains(addr)) ) {
00595                                 localIPAddresses.add(addr);
00596                         }
00597                 }
00598 
00599 
00600         return localIPAddresses;
00601 }
00602 
00603 Dictionary JSocket::getLocalInterfaceAddresses() {
00604 
00605         Dictionary dict;
00606 
00607         #ifdef WIN32
00608 
00609                 unsigned long size = 10000;
00610                 void* mem = malloc(size);
00611                 IP_ADAPTER_INFO* adaptors = (IP_ADAPTER_INFO*) mem;
00612 
00613                 int res = GetAdaptersInfo(adaptors, &size);
00614                 if (res != ERROR_SUCCESS) {
00615                         free(mem);
00616                         return dict;
00617                 }
00618 
00619                 JString adaptor, addr;
00620                 while (adaptors != NULL) {
00621 
00622                         
00623                                 adaptor = adaptors->Description;
00624                                 addr = adaptors->IpAddressList.IpAddress.String;
00625                                 if (addr.length() > 0)
00626                                         dict.put(adaptor, addr);
00627 
00628                         adaptors = (IP_ADAPTER_INFO*) adaptors->Next;
00629                 }
00630 
00631                 free(mem);
00632 
00633         #else
00634                 int sock = 0;
00635                 struct ifreq ifreq;
00636                 struct sockaddr_in *saptr = NULL;
00637                 struct if_nameindex *iflist = NULL, *listsave = NULL;
00638 
00639                 
00640                 if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00641                         return dict;
00642                 }
00643 
00644                 
00645                 iflist = listsave = if_nameindex();
00646 
00647                 if (iflist == NULL) {
00648                         close(sock);
00649                         return dict;
00650                 }
00651 
00652                 JString key, addr;
00653                 
00654                 
00655                 for(iflist; iflist->if_index != 0; iflist++) {
00656                         
00657                         strncpy(ifreq.ifr_name, iflist->if_name, IF_NAMESIZE);
00658                         
00659                         if(ioctl(sock, SIOCGIFADDR, &ifreq) != 0) {
00660                                 
00661                                 continue;
00662                         }
00663                         
00664                         saptr = (struct sockaddr_in *)&ifreq.ifr_addr;
00665                 
00666                         key = ifreq.ifr_name;
00667                         addr = JString::format("%d.%d.%d.%d", NIPQUAD(saptr->sin_addr.s_addr));
00668                         dict.put(key, addr);
00669                 }
00670                 
00671                 if_freenameindex(listsave);
00672                 close(sock); 
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715         #endif
00716 
00717         return dict;
00718 }
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 JString JSocket::getLocalHostname() {
00727 
00728 
00729         #if defined(_WIN32_WCE)
00730                 return getLocalIPAddress();
00731         #endif
00732         
00733         if (localhostName.length() > 0)
00734                 return localhostName;
00735 
00736         char* hname = new char[1000];
00737         if (gethostname(hname, 1000) == 0) {
00738                 localhostName = hname;
00739                 delete [] hname;
00740                 return localhostName;
00741         }
00742         delete [] hname;
00743 
00744         JString ipaddress = getLocalIPAddress();
00745         JString hostname = ipaddress;
00746         struct hostent* hent;
00747         if ( (ipaddress.equals("127.0.0.1")) || (ipaddress.equals("localhost")) ) {
00748                 localhostName = "127.0.0.1";
00749                 return localhostName;
00750         }
00751 
00752         #ifdef WIN32
00753 
00754                 hent = gethostbyname((char*) ipaddress);
00755 
00756                 if (hent != NULL)
00757                         localhostName = JString(hent->h_name);
00758                 else {
00759                         int err = WSAGetLastError();
00760 
00761                         if (DEBUGLEVEL(KITCHENSINK)) {
00762                                 printf("getLocalHostname(): gethostbyaddr error %d...\n", err);
00763                         }
00764                         localhostName = ipaddress;
00765                         return ipaddress;
00766                 }
00767 
00768         #else // WIN32
00769 
00770                 struct addrinfo hints, *res;
00771                 int error;
00772                 const char *cause = NULL;
00773 
00774                 memset(&hints, 0, sizeof(hints));
00775                 hints.ai_flags = AI_NUMERICHOST;
00776                 hints.ai_family = PF_UNSPEC;
00777                 hints.ai_socktype = SOCK_STREAM;
00778 
00779 
00780                 error = getaddrinfo(ipaddress, NULL, &hints, &res);
00781 
00782                 if (error != 0) {
00783                         localhostName = ipaddress;
00784                         return ipaddress;
00785                 }
00786                 else {
00787                         if (res->ai_canonname != NULL) {
00788                                 localhostName = res->ai_canonname;
00789 
00790                         }
00791                         else
00792                                 localhostName = ipaddress;
00793                 }
00794                 freeaddrinfo(res);
00795 
00796 
00797 
00798 
00799 
00800 
00801 
00802 
00803 
00804 
00805 
00806 
00807 
00808 
00809 
00810 
00811 
00812 
00813 
00814 
00815 
00816 
00817 
00818 
00819 
00820 
00821 
00822 
00823 
00824 
00825 
00826 
00827 
00828 
00829 
00830 
00831 
00832 
00833 
00834 
00835 
00836 
00837         #endif // WIN32
00838 
00839         return localhostName;
00840 
00841 
00842 
00843 
00844 
00845 
00846 
00847 
00848 
00849 
00850 
00851 
00852 
00853 
00854 
00855 
00856 
00857 
00858 
00859 
00860 
00861 
00862 
00863 
00864 
00865 
00866 
00867 
00868 
00869 
00870 
00871 
00872 
00873 
00874 
00875 
00876 
00877 
00878 
00879 
00880 
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 
00889 
00890 
00891 
00892 
00893 
00894 
00895 
00896 
00897 
00898 
00899 
00900 
00901 
00902 
00903 
00904 
00905 
00906 
00907 
00908 
00909 
00910 
00911 
00912 
00913 
00914 
00915 
00916 
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 
00928 
00929 
00930 
00931 
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939 
00940 
00941 
00942 
00943 
00944 
00945 
00946 
00947 
00948 
00949 
00950 
00951 
00952 
00953 
00954 
00955 
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968 
00969 }
00970 
00971 JString JSocket::getRemoteIPAddress() {
00972 
00973         if (!isSocketValid()) return "";
00974 
00975         JString ipaddr;
00976 
00977         struct sockaddr_in remoteAddr;
00978         
00979         #ifdef WIN32
00980                 int remoteAddrLen;
00981         #else
00982                 #ifdef Darwin
00983                         #if GCC_VERSION < 40000
00984                                 int remoteAddrLen;
00985                         #else
00986                                 socklen_t remoteAddrLen;
00987                         #endif // GCC_VERSION < 40000
00988                 #else
00989                         socklen_t remoteAddrLen;
00990                 #endif
00991         #endif // WIN32
00992 
00993         remoteAddrLen = sizeof(struct sockaddr_in);
00994 
00995         if (getpeername(mySocket, (struct sockaddr*) &remoteAddr, &remoteAddrLen) == 0) {
00996                 ipaddr = inet_ntoa(remoteAddr.sin_addr);
00997                 if ((ipaddr.equals("127.0.0.1")) || (ipaddr.equals("localhost"))) {
00998                         ipaddr = getLocalIPAddress();
00999                 }
01000                 this->address = ipaddr;
01001                 this->port = (int) remoteAddr.sin_port;
01002         }
01003         return ipaddr;
01004 }
01005 
01006 
01007 JString JSocket::getRemoteHostname() {
01008         return getHostnameFromIPAddress(getRemoteIPAddress());
01009 }
01010 
01011 
01012 JString JSocket::getHostnameFromIPAddress(JString ipaddr) {
01013 
01014         #if defined(_WIN32_WCE)
01015                 return ipaddr;
01016         #endif
01017 
01018         if (ipaddr.length() == 0)
01019                 return ipaddr;
01020 
01021         JString hname = ipaddr;
01022 
01023         struct hostent *pHost;
01024 
01025         #ifdef WIN32
01026                 pHost = gethostbyname(ipaddr);
01027                 if (pHost == NULL)
01028                         return ipaddr;
01029                 hname = pHost->h_name;
01030         #else // WIN32
01031 
01032                 #ifdef Darwin
01033                     pHost = gethostbyname(ipaddr);
01034                     if (pHost == NULL)
01035                                 return ipaddr;
01036                         else
01037                                 hname = pHost->h_name;
01038                 #else // Darwin
01039 
01040                         pHost = new struct hostent;
01041                         char bf[2000];
01042                         int er;
01043                         gethostbyname_r(ipaddr, pHost, bf, 2000, &pHost, &er);
01044                         if (er != 0) {
01045                                 delete pHost;
01046                                 return ipaddr;
01047                         }
01048                         else {
01049                                 hname = pHost->h_name;
01050                                 delete pHost;
01051                         }
01052 
01053                 #endif // Darwin
01054         #endif // WIN32
01055 
01056         if ((hname.equals("127.0.0.1")) || (hname.equals("localhost"))) {
01057                 hname = getLocalHostname();
01058         }
01059         return hname;
01060 }
01061 
01062 
01063 
01064 
01065 
01066 
01067 
01068 
01069 JSocket::JSocket(SOCKET new_sock) {
01070 
01071 
01072 
01073         charBufferCount = 0;
01074         charBuffer[0] = 0;
01075         mySocket = new_sock;
01076         protocol = "";
01077 
01078         getRemoteHostname();
01079 
01080 
01081         setNonBlockingMode();
01082 
01083         connected = true;
01084         lastErrorMessage = "";
01085         lastErrorRecoverable = true;
01086         listening = false;
01087 
01088 }
01089 
01090 
01091 
01092 
01093 bool JSocket::setUpListening() {
01094 
01095         if ((isSocketValid()) || (isListening())) {
01096                 if (DEBUGLEVEL(KITCHENSINK)) {
01097                         printf("****** CreateSocket failed, socket already there! *****/n");
01098                 }
01099                 return false;
01100         }
01101 
01102         listening = false;
01103         if (!createSocket()) {
01104                 if (DEBUGLEVEL(KITCHENSINK)) {
01105                         printf("****** CreateSocket failed! *****/n");
01106                 }
01107                 return false;
01108         }
01109 
01110         if (!isSocketValid()) {
01111                 if (DEBUGLEVEL(STATUS)) {
01112                         printf("Just created an invalid socket!/n");
01113                 }
01114                 wait(1000);
01115                 return false;
01116         }
01117 
01118         
01119         
01120         
01121         struct sockaddr_in saServer;
01122 
01123         saServer.sin_family = AF_INET;
01124         saServer.sin_addr.s_addr = INADDR_ANY;          
01125         saServer.sin_port = htons(port);                
01126 
01127         int res;
01128 
01129         #ifndef WIN32
01130                 
01131 
01132 
01133 
01134 
01135 
01136 
01137 
01138 
01139                 int one = 1;
01140                 setsockopt(mySocket,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
01141         #endif
01142 
01143         
01144         if ((res = bind(mySocket, (struct sockaddr *)&saServer, sizeof(struct sockaddr_in))) < 0) {
01145                 if (DEBUGLEVEL(DETAILEDSTATUS)) {
01146                         printf("****** Bind not performed *****\n");
01147                 }
01148                 dealWithSocketError(getLastOSErrorNumber(), "Bind failed");
01149                 disconnectNow();
01150                 return false;
01151         }
01152 
01153         if ((res = listen(mySocket, SOMAXCONN)) < 0) {  
01154                 if (DEBUGLEVEL(DETAILEDSTATUS)) {
01155                         printf("****** Listening not started *****\n");
01156                 }
01157                 dealWithSocketError(getLastOSErrorNumber(), "Listen failed");
01158                 disconnectNow();
01159                 return false;
01160         }
01161 
01162         listening = true;
01163         connected = false;
01164 
01165         return true;
01166 }
01167 
01168 JSocket* JSocket::waitForConnection(long timeout) {
01169 
01170         JTime now;
01171 
01172         JTime t;
01173         lastErrorMessage = "";
01174         
01175         
01176         if (!isSocketValid()) {
01177                 if (DEBUGLEVEL(KITCHENSINK)) {
01178                         printf("######## WAITING for invalid socket %d!\n", mySocket);
01179                 }
01180                 wait(100);
01181                 return NULL;
01182         }
01183         if (!isListening()) {
01184                 if (DEBUGLEVEL(KITCHENSINK)) {
01185                         printf("######## WAITING for non-listening socket!\n");
01186                 }
01187                 wait(100);
01188                 return NULL;
01189         }
01190 
01191         bool waitingForAccept = true;
01192         int w;
01193 
01194         SOCKET new_sock = INVALID_SOCKET;
01195         while (waitingForAccept) {
01196 
01197         
01198         
01199                 new_sock = accept(mySocket, NULL, NULL);
01200         
01201         
01202 
01203                 if ((int) new_sock < 0) {
01204                         int wsaError = getLastOSErrorNumber();
01205                         if ((wsaError == WSAEWOULDBLOCK) || (wsaError == EINPROGRESS)) {
01206                                 
01207                                 now = JTime();
01208                                 w = timeout - (now-t);
01209                                 
01210                                 if (w > 0) {
01211                                         
01212                                 
01213                                         waitForReadability(w);
01214                                 
01215                                 
01216                                 }
01217                                 else
01218                                         break;
01219                         }
01220                         else {
01221                         
01222                         
01223                                 dealWithSocketError(wsaError, "Accept failed");
01224                                 if (DEBUGLEVEL(KITCHENSINK)) {
01225                                         printf("######## JSocket : Accept failed %d ##########\n", wsaError);
01226                                 }
01227                                 wait(100);
01228                                 disconnectNow();
01229                         
01230                         
01231                                 return NULL;
01232                         }
01233                 }
01234                 else {
01235                         
01236                 
01237                 
01238                         JSocket* s = new JSocket(new_sock);
01239                 
01240                 
01241                         return s;
01242                 }
01243         }
01244 
01245 
01246 
01247         return NULL;
01248 }
01249         
01250 
01251 
01252 
01253 
01254 IPNumber JSocket::getIPNumberFromName(JString name) {
01255 
01256         IPNumber ipnum;
01257         ipnum.a = ipnum.b = ipnum.c = ipnum.d = 0;
01258 
01259         if (name.length() == 0) {
01260                 ipnum.a = 127;
01261                 ipnum.b = 0;
01262                 ipnum.c = 0;
01263                 ipnum.d = 1;
01264                 return ipnum;
01265         }
01266 
01267         struct hostent* hent;
01268         JString lookupName = name;
01269 
01270         Collection col = lookupName.split(".");
01271         if (col.getCount() == 4) {
01272                 int num = col.getFirst().toInt();
01273                 if (num > 0) {
01274                         ipnum.a = num;
01275                         ipnum.b = col.getNext().toInt();
01276                         ipnum.c = col.getNext().toInt();
01277                         ipnum.d = col.getNext().toInt();
01278                         return ipnum;
01279                 }
01280         }
01281 
01282 
01283 
01284         if ((name.equalsIgnoreCase("localhost") || name.equalsIgnoreCase("127.0.0.1"))) {
01285                 lookupName = getLocalIPAddress();
01286                 col = lookupName.split(".");
01287                 if (col.getCount() == 4) {
01288                         ipnum.a = col.get(0).toInt();
01289                         ipnum.b = col.get(1).toInt();
01290                         ipnum.c = col.get(2).toInt();
01291                         ipnum.d = col.get(3).toInt();
01292                 }
01293                 else {
01294                         if (DEBUGLEVEL(STATUS)) {
01295                                 printf("Unable to find IPNumber for localhost, defaulting to 127.0.0.1...");
01296                         
01297                         }
01298                         ipnum.a = 127;
01299                         ipnum.b = 0;
01300                         ipnum.c = 0;
01301                         ipnum.d = 1;
01302                 }
01303                 return ipnum;
01304         }
01305 
01306         #ifdef WIN32
01307                 
01308                 hent = gethostbyname(lookupName);
01309 
01310                 if (hent == NULL) {
01311                         dealWithSocketError(getLastOSErrorNumber(), "Hostname invalid in connectNow");
01312                 }
01313                 else
01314                         memcpy(&ipnum, hent->h_addr_list[0], 4);
01315 
01316         #else
01317                 struct addrinfo hints, *res;
01318                 int error;
01319                 const char *cause = NULL;
01320 
01321 
01322 
01323                 memset(&hints, 0, sizeof(hints));
01324                 
01325                 hints.ai_family = PF_UNSPEC;
01326                 hints.ai_socktype = SOCK_STREAM;
01327 
01328                 error = getaddrinfo(lookupName, NULL, &hints, &res);
01329 
01330                 if (!error) {
01331                         ipnum.a = res->ai_addr->sa_data[2];
01332                         ipnum.b = res->ai_addr->sa_data[3];
01333                         ipnum.c = res->ai_addr->sa_data[4];
01334                         ipnum.d = res->ai_addr->sa_data[5];
01335                         freeaddrinfo(res);
01336                 }
01337                 else {
01338                   if (DEBUGLEVEL(STATUS))
01339                     printf("getaddrinfo error: %d (%s)\n", error, gai_strerror(error));
01340                 }
01341         #endif // WIN32
01342 
01343 
01344 
01345 
01346 
01347 
01348 
01349 
01350 
01351                         
01352         return ipnum;
01353 }
01354 
01355 JString JSocket::getIPAddressFromName(JString name) {
01356         IPNumber ipnum = getIPNumberFromName(name);
01357         return JString::format("%d.%d.%d.%d", ipnum.a, ipnum.b, ipnum.c, ipnum.d);
01358 }
01359 
01360 
01361 
01362 bool JSocket::connectNow(const IPNumber& ip, int port) {
01363 
01364         struct sockaddr_in saServer;
01365         saServer.sin_family = AF_INET;
01366         saServer.sin_port = htons(port);
01367         
01368         memcpy(&saServer.sin_addr, &ip, 4);
01369 
01370         
01371         connected = true;
01372         listening = false;
01373 
01374         
01375         int res;
01376         if ((res = connect(mySocket, (struct sockaddr*)&saServer, sizeof(struct sockaddr))) != 0) {
01377 
01378                 int wsaError = getLastOSErrorNumber();
01379                 if ((wsaError == WSAEWOULDBLOCK) || (wsaError == EINPROGRESS)) {
01380                         if (DEBUGLEVEL(DETAILEDSTATUS)) {
01381                                 printf("Waiting for Socket to connect to %d.%d.%d.%d:%d [%d]...", ip.a, ip.b, ip.c, ip.d, port, wsaError);      
01382                         }
01383                         if (!didConnectionGoThrough(300)) {
01384                           if (DEBUGLEVEL(DETAILEDSTATUS))
01385                             printf(" FAILED\n");        
01386                                 disconnectNow();
01387                                 connected = false;
01388                                 return false;
01389                         }
01390                         if (DEBUGLEVEL(DETAILEDSTATUS))
01391                                 printf(" SUCCESS\n");   
01392                 }
01393                 else {
01394                         if (DEBUGLEVEL(DETAILEDSTATUS)) {
01395                                 printf("Socket could not connect to %d.%d.%d.%d:%d [%d]...\n", ip.a, ip.b, ip.c, ip.d, port, wsaError); 
01396                         }
01397                         disconnectNow();
01398                         connected = false;
01399                         return false;
01400                 }
01401         }
01402 
01403         connected = true;
01404         return true;
01405 
01406 }
01407 
01408 
01409 bool JSocket::connectNow() {
01410 
01411         if (!isSocketValid()) {
01412                 if (!createSocket())
01413                         return false;
01414         }
01415 
01416         Collection addresses = this->location.getAllAddresses();
01417 
01418         bool res = false;
01419         IPNumber ip;
01420         JString conAddress;
01421         for (int n=0; n<addresses.getCount(); n++) {
01422                 if ( (conAddress = addresses.get(n)).length() > 0) {
01423                         ip = getIPNumberFromName(conAddress);
01424                         if (ip.a > 0) {
01425                                 res = connectNow(ip, port);
01426                                 if (res) {
01427                                         ipnumber = ip;
01428                                         address = conAddress;
01429                                         return true;
01430                                 }
01431                         }
01432                 }
01433         }
01434         return res;
01435 }
01436 
01437 
01438 
01439 bool JSocket::disconnectNow() {
01440         if (isSocketValid())
01441                 osCloseSocket(mySocket);
01442         setSocketNotValid();
01443         connected = listening = false;
01444         
01445 
01446         return true;
01447 }
01448 
01449 int JSocket::readChar(char* ch) {
01450         if (!isConnected())
01451                 return -1;
01452 
01453         int res;
01454         int wsaError;
01455 
01456         if ((res = recv(mySocket, ch, 1, 0)) > 0) {
01457                 ioCounts[0]++;
01458                 return 1;
01459         }
01460         
01461         if (res == 0) {
01462                 connected = false;
01463                 return -1;
01464         }
01465 
01466         else {
01467                 wsaError = getLastOSErrorNumber();
01468                 if ((wsaError == WSAEWOULDBLOCK) || (wsaError == EINPROGRESS)) {
01469                         
01470                         return 0;
01471                 }
01472                 else if (wsaError == WSAEMSGSIZE) {
01473                         
01474                         ioCounts[0]++;
01475                         return 1;
01476                 }
01477                 else {
01478                         dealWithSocketError(wsaError, "Read failed");
01479                         if (!lastErrorRecoverable) {
01480                                 disconnectNow();
01481                                 return -1;
01482                         }
01483                         return 0;
01484                 }
01485         }
01486 }
01487 
01488 int JSocket::peekIntoStream() {
01489         char peekBuffer[1];
01490         return peekIntoStream(peekBuffer, 1);
01491 }
01492 
01493 int JSocket::peekIntoStream(char* buffer, int maxcount) {
01494         if (!isSocketValid())
01495                 return -1;
01496         int res = recv(mySocket, buffer, maxcount, MSG_PEEK);
01497 
01498         if (res <= 0) {
01499                 int wsaError = getLastOSErrorNumber();
01500                 if (((wsaError == WSAEWOULDBLOCK) || (wsaError == EINPROGRESS))) {
01501                         
01502                         return 0;
01503                 }
01504                 else {
01505                         if (wsaError == WSAENOTCONN) { 
01506                                 
01507                                 
01508                         }
01509                         #ifdef WIN32
01510                         else if (wsaError == WSAEOPNOTSUPP) { 
01511                                 
01512                                 
01513                         }
01514                         
01515                         
01516                                 
01517                         
01518                         #endif //WIN32
01519                         else {
01520                                 
01521                                 int so = (int) mySocket;
01522                                 disconnectNow();
01523                                 dealWithSocketError(wsaError, "Read failed");
01524                         }
01525                         return -1;
01526                 }
01527 
01528         }
01529         return res;
01530 }
01531 
01532 
01533 int JSocket::readIntoBuffer() {
01534         if (!isSocketValid())
01535                 return -1;
01536         int count = 0;
01537         unsigned int breakmax = BUFFERSIZE - charBufferCount;
01538         if (breakmax < 0) 
01539                 return -2;
01540         else if (breakmax == 0)
01541                 return 0;
01542 
01543         
01544         
01545         
01546 
01547         int res;
01548         int wsaError;
01549         JString text;
01550 
01551         while ((res = recv(mySocket, (char*)(charBuffer + charBufferCount), breakmax, 0)) > 0) {
01552                 charBufferCount += res;
01553                 count += res;
01554                 
01555                 breakmax = BUFFERSIZE - charBufferCount;
01556                 if (breakmax <= 0) {
01557                         ioCounts[0] += count;
01558                         return count;
01559                 }
01560         }
01561 
01562         wsaError = getLastOSErrorNumber();
01563 
01564         if ((res < 0) && ((wsaError == WSAEWOULDBLOCK) || (wsaError == EINPROGRESS))) {
01565                 
01566                 ioCounts[0] += count;
01567                 return count;
01568         }
01569         else if (res == 0) {
01570                 if (count == 0)
01571                         count = -1;
01572                 
01573                 
01574         }
01575         else {
01576                 if (count == 0)
01577                         count = -1;
01578 
01579                 if (wsaError == WSAEMSGSIZE) {
01580                         
01581                         ioCounts[0] += count;
01582                         return count;
01583                 }
01584                 else {
01585                         dealWithSocketError(wsaError, "Read failed");
01586                 }
01587         }
01588 
01589         if (count < 0)
01590                 disconnectNow();
01591 
01592         ioCounts[0] += count;
01593         return count;
01594 }
01595 
01596 
01597 int JSocket::writeString(JString text) {
01598         return writeBuffer(text, text.length());
01599 }
01600 
01601 int JSocket::writeBuffer(char* buf, int length) {
01602         int breakmax = SENDBUFFERSIZE;
01603         
01604         if (!isConnected()) return -1;
01605         if (length == 0) return 0;
01606 
01607         currentUnsentBufferSize = length;
01608         currentSentBufferSize = 0;
01609 
01610         int wsaError;
01611         int res = 0;
01612 
01613         setBlockingMode();
01614 
01615         JTime t1, t2;
01616         if (length <= breakmax) {
01617                 res = send(mySocket, buf, length, 0);
01618                 
01619                 waitForWriteability(1000);
01620                 
01621                 
01622         }
01623         else {
01624                 int subres = 0;
01625                 char* lpbuffer = buf;
01626                 int l = length;
01627                 int n = l / breakmax;
01628                 for (int i=0; i < n; i++) {
01629                         subres = send(mySocket, &lpbuffer[i*breakmax], breakmax, 0);
01630                         if (subres == breakmax) {
01631                                 res += subres;
01632                                 currentSentBufferSize = res;
01633                         }
01634                         else {
01635                         
01636                                 currentUnsentBufferSize = 0;
01637                                 currentSentBufferSize = 0;
01638                                 connected = false;
01639                                 return -1;
01640                         }
01641 
01642                         
01643                         waitForWriteability(1000);
01644                         
01645                         
01646                 }
01647                 
01648                 n = n * breakmax;
01649                 
01650                 subres = send(mySocket, &lpbuffer[n], l-n, 0);
01651                 if (subres == l-n) {
01652                         res += subres;
01653                         currentSentBufferSize = res;
01654                 }
01655                 else {
01656                         
01657                         currentUnsentBufferSize = 0;
01658                         currentSentBufferSize = 0;
01659                         connected = false;
01660                         return -1;
01661                 }
01662                 
01663                 waitForWriteability(1000);
01664                 
01665                 
01666         }
01667 
01668         setNonBlockingMode();
01669 
01670 
01671 
01672 
01673         
01674 
01675 
01676 
01677 
01678 
01679 
01680 
01681 
01682 
01683 
01684 
01685 
01686 
01687 
01688         
01689 
01690 
01691 
01692 
01693 
01694 
01695 
01696 
01697 
01698 
01699 
01700 
01701 
01702 
01703 
01704 
01705 
01706 
01707 
01708 
01709         
01710 
01711         if (res == length) {
01712                 currentSentBufferSize = length;
01713                 ioCounts[1] += length;
01714                 return length;
01715         }
01716         else if (res > 0) {
01717                 printf("*** Only partial socket send - %d out of %d ***\n", res, length);
01718                 currentUnsentBufferSize = 0;
01719                 currentSentBufferSize = 0;
01720                 connected = false;
01721                 return -1;
01722         }
01723         
01724         if (res == 0) {
01725                 currentUnsentBufferSize = 0;
01726                 currentSentBufferSize = 0;
01727                 connected = false;
01728                 return -1;
01729         }
01730 
01731         else {
01732                 wsaError = getLastOSErrorNumber();
01733                 if (wsaError == 0) {
01734                         
01735                         if (DEBUGLEVEL(DETAILEDSTATUS))
01736                                 printf("*** No error, just unable to send... ***\n");
01737                         currentUnsentBufferSize = 0;
01738                         currentSentBufferSize = 0;
01739                         return -1;
01740                 }
01741                 else if ((wsaError == WSAEWOULDBLOCK) || (wsaError == EINPROGRESS)) {
01742                         
01743                         if (!isConnected(1000)) {
01744                                 if (DEBUGLEVEL(DETAILEDSTATUS))
01745                                         printf("*** Not connected error, unable to send... ***\n");
01746                                 currentUnsentBufferSize = 0;
01747                                 currentSentBufferSize = 0;
01748                                 return -1;
01749                         }
01750                         
01751                         
01752                         currentSentBufferSize = length;
01753                         ioCounts[1] += length;
01754                         return length;
01755                 }
01756                 else if (wsaError == WSAEMSGSIZE) {
01757                         
01758                         if (DEBUGLEVEL(DETAILEDSTATUS))
01759                                 printf("*** Buffer full error, unable to send... ***\n");
01760                         currentUnsentBufferSize = 0;
01761                         currentSentBufferSize = 0;
01762                         return -2;
01763                 }
01764                 else {
01765                         dealWithSocketError(wsaError, "Write failed");
01766                         if (!lastErrorRecoverable) {
01767                                 if (DEBUGLEVEL(DETAILEDSTATUS)) {
01768                                 
01769                                         printf("*** Socket error, unable to send... ***\n");
01770                                 }
01771                                 disconnectNow();
01772                                 currentUnsentBufferSize = 0;
01773                                 currentSentBufferSize = 0;
01774                                 return -1;
01775                         }
01776                         currentUnsentBufferSize = 0;
01777                         currentSentBufferSize = 0;
01778                         return -1;
01779                 }
01780         }
01781 }
01782 
01783 
01784 bool JSocket::isConnected(int timeout) {
01785 
01786 
01787 
01788 
01789 
01790 
01791 
01792         
01793         int peek = peekIntoStream();
01794 
01795         if (peek < 0) {
01796                 peek = peek + 1 - 1;
01797         }
01798 
01799 
01800         int maxfd = 0;
01801 
01802 
01803         if (!isSocketValid()) {
01804                 if (DEBUGLEVEL(DETAILEDSTATUS)) {
01805                 
01806 
01807 
01808 
01809 
01810         
01811                         
01812                 }
01813                 
01814                 return false;
01815         }
01816 
01817         struct timeval tv;
01818         tv.tv_sec = 0;
01819         tv.tv_usec = 10;
01820 
01821         fd_set wfds;
01822 
01823         
01824         FD_ZERO(&wfds);
01825         
01826         FD_SET(mySocket, &wfds);
01827 
01828         #ifdef WIN32
01829                 int len;
01830         #else
01831                 #ifdef Darwin
01832                         #if GCC_VERSION < 40000
01833                                 int len;
01834                                 maxfd = mySocket + 1;
01835                         #else
01836                                 socklen_t len;
01837                                 maxfd = mySocket + 1;
01838                         #endif // GCC_VERSION < 40000
01839                 #else
01840                         socklen_t len;
01841                         maxfd = mySocket + 1;
01842                 #endif
01843         #endif
01844 
01845         if (timeout > 0) {
01846                 ldiv_t d = ldiv(timeout*1000, 1000000);
01847                 tv.tv_sec = d.quot;
01848                 tv.tv_usec = d.rem;
01849         }
01850 
01851         
01852         int res = select(maxfd, NULL, &wfds, NULL, &tv);
01853 
01854         if (res <= 0) {
01855                 if (DEBUGLEVEL(DETAILEDSTATUS)) {
01856                 
01857                 }
01858                 
01859                 return false;
01860         }
01861 
01862         int error;
01863         len = sizeof(error);
01864 
01865         if (FD_ISSET(mySocket, &wfds) != 0) {
01866                 if (getsockopt(mySocket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
01867 
01868                         int wsaError = getLastOSErrorNumber();
01869                         if (wsaError == 0) {
01870                                 
01871                                 
01872                                 return true;
01873                         }
01874                         #ifdef WIN32
01875                                 else if (wsaError == WSAENETDOWN ) {
01876                                         
01877                                         return false;
01878                                 }
01879                                 else if (wsaError == WSAEFAULT  ) {
01880                                         
01881                                         return false;
01882                                 }
01883                                 else if (wsaError == WSAEINPROGRESS  ) {
01884                                         
01885                                         return false;
01886                                 }
01887                                 else if (wsaError == WSAEINVAL  ) {
01888                                         
01889                                         return false;
01890                                 }
01891                                 else if (wsaError == WSAENOPROTOOPT  ) {
01892                                         if (error == 0) {
01893                                                 
01894                                                 return true;
01895                                         }
01896                                 }
01897                                 else if (wsaError == WSAENOTSOCK  ) {
01898                                         
01899                                         return false;
01900                                 }
01901                         #endif                  
01902                         printf("**********************  getsockopt failed  *************************");
01903                         
01904                         return false;
01905                 }
01906                 if (error == 0) {
01907                         
01908 
01909                         
01910                         return true;
01911                 }
01912         }
01913 
01914         if (DEBUGLEVEL(DETAILEDSTATUS)) {
01915         
01916         }
01917         
01918         return false;
01919 }
01920 
01921 bool JSocket::waitForReadability(int timeout) {
01922 
01923         int maxfd = 0;
01924 
01925         
01926         if (!isSocketValid()) return true;
01927 
01928         struct timeval tv;
01929         tv.tv_sec = 0;
01930         tv.tv_usec = 0;
01931 
01932         fd_set rdds;
01933         
01934         FD_ZERO(&rdds);
01935         
01936         FD_SET(mySocket, &rdds);
01937 
01938         #ifdef WIN32
01939         #else
01940                 #ifdef Darwin
01941                         maxfd = mySocket + 1;
01942                 #else
01943                         maxfd = mySocket + 1;
01944                 #endif
01945         #endif
01946 
01947         if (timeout > 0) {
01948                 ldiv_t d = ldiv(timeout*1000, 1000000);
01949                 tv.tv_sec = d.quot;
01950                 tv.tv_usec = d.rem;
01951         }
01952 
01953         
01954 
01955         int ret = select(maxfd, &rdds, NULL, NULL, &tv);
01956 
01957 
01958 
01959 
01960         return(ret > 0);
01961 }
01962 
01963 bool JSocket::waitForWriteability(int timeout) {
01964 
01965         int maxfd = 0;
01966 
01967         
01968         if (!isSocketValid()) return true;
01969 
01970         struct timeval tv;
01971         tv.tv_sec = 0;
01972         tv.tv_usec = 0;
01973 
01974         fd_set wds;
01975         
01976         FD_ZERO(&wds);
01977         
01978         FD_SET(mySocket, &wds);
01979 
01980         #ifdef WIN32
01981         #else
01982                 #ifdef Darwin
01983                         maxfd = mySocket + 1;
01984                 #else
01985                         maxfd = mySocket + 1;
01986                 #endif
01987         #endif
01988 
01989         if (timeout > 0) {
01990                 ldiv_t d = ldiv(timeout*1000, 1000000);
01991                 tv.tv_sec = d.quot;
01992                 tv.tv_usec = d.rem;
01993         }
01994 
01995         
01996         return( select(maxfd, NULL, &wds, NULL, &tv) > 0);
01997 }
01998 
01999 bool JSocket::didConnectionGoThrough(int timeout) {
02000         return isConnected(timeout);
02001 }
02002 
02003 bool JSocket::isIPAddressPrivate(JString ipaddr) {
02004 
02005         bool res = false; 
02006 
02007         if (ipaddr.equals("127.0.0.1"))
02008                 res = true;
02009         else if (ipaddr.startsWith("10."))
02010                 res = true;
02011         else if (ipaddr.startsWith("192.168."))
02012                 res = true;
02013         else if (ipaddr.startsWith("0."))
02014                 res = true;
02015 
02016         return res;
02017 }
02018 
02019 
02020 
02021 double JSocket::getReceiveProgress() {
02022         if (currentUnreceivedBufferSize == 0)
02023                 return 1;
02024         else if (currentUnreceivedBufferSize == currentReceivedBufferSize)
02025                 return 1;
02026         else if (currentUnreceivedBufferSize > currentReceivedBufferSize)
02027                 return ((double)currentReceivedBufferSize)/((double)currentUnreceivedBufferSize);
02028         else
02029                 return 1;
02030 }
02031 
02032 double JSocket::getSendProgress() {
02033         if (currentUnsentBufferSize == 0)
02034                 return 1;
02035         else if (currentUnsentBufferSize == currentSentBufferSize)
02036                 return 1;
02037         else if (currentUnsentBufferSize > currentSentBufferSize)
02038                 return ((double)currentSentBufferSize)/((double)currentUnsentBufferSize);
02039         else
02040                 return 1;
02041 }
02042 
02043 
02044 
02045 double* JSocket::getIOCounts() {
02046         if (ioCounts[0] < 0) ioCounts[0] = 0;
02047         if (ioCounts[1] < 0) ioCounts[1] = 0;
02048         return ioCounts;
02049 }
02050 
02051 bool JSocket::resetIOCounts() {
02052         ioCounts[0] = ioCounts[1] = 0;
02053         return true;
02054 }
02055 
02056 
02057 
02058 
02059 
02060 
02061 
02062 
02063 
02064 
02065 
02066 
02067 
02068 
02069 
02070 
02071 
02072 
02073 
02074 
02075 
02076 
02077 
02078 
02079 
02080 
02081 
02082 
02083 
02084 
02085 
02086 
02087 
02088 
02089 
02090 
02091 
02092 
02093 
02094 
02095 
02096 
02097 
02098 
02099 
02100 
02101 
02102 
02103 
02104 
02105 
02106 
02107 
02108 
02109 
02110 
02111 
02112 
02113 
02114 
02115 
02116 
02117 SocketTester::SocketTester(int port) : JThread() {
02118         portnum = port;
02119         server = NULL;
02120 }
02121 
02122 SocketTester::~SocketTester() {
02123         shouldContinue = false;
02124 
02125 
02126         int count = 0;
02127         while (server != NULL) {
02128                 wait(50);
02129                 if (count++ > 20)
02130                         break;
02131         }
02132 }
02133 
02134 void SocketTester::run() {
02135 
02136         char* buf;
02137 
02138         printf("Starting server\n");
02139         this->addUnitTestLog("Socket Server starting...");
02140 
02141 
02142         JSocket* c = NULL;
02143         server = new JSocket("", portnum, "");
02144 
02145         if (!server->setUpListening()) {
02146                 printf("\nPort %d not available.\n", portnum);
02147                 this->addUnitTestLog("Socket Server port not available...");
02148                 return;
02149         }
02150 
02151 
02152 
02153         JString str;
02154         
02155         shouldContinue = true;
02156 
02157         int count = 0;
02158         JTime t;
02159 
02160         while (shouldContinue) {
02161 
02162                 
02163                 t = JTime();
02164                 
02165                 c = server->waitForConnection(50);
02166                 t = JTime();
02167                 
02168                 server->getUnitTestLog();
02169 
02170                 t = JTime();
02171                 if (c != NULL) {
02172                         
02173 
02174                         
02175 
02176 
02177                         while (c->isConnected()) {
02178                                 
02179                                 str = c->readln(500);
02180                                 if (str.length() > 0) {
02181 
02182                                   
02183                                   if (str.length() < 9) {
02184                                     int len = str.toInt();
02185                                     if (len > 0) {
02186                                       buf = new char[len+1];
02187                                       if (c->read(buf, len, MSGTIMEOUT) < len) {
02188                                                 printf("Server Read Error\n");
02189                                       }
02190                                       else {
02191                                                 buf[len] = 0;
02192                                                 
02193                                                 JString str3 = JString((int)len) + JString("\n") + JString(buf);
02194                                                 if (c->writeString(str3) <= 0) {
02195                                                         printf("!"); fflush(stdout);
02196                                                 
02197                                                 
02198                                                 
02199                                                 }
02200                                                 else {
02201                                                         
02202                                                 }
02203                                       }
02204                                       delete [] buf;
02205                                       buf=NULL;
02206                                     }
02207                                   }
02208                                   else {
02209 
02210 
02211                                           
02212 
02213 
02214                                         c->writeln(str);
02215                                   }
02216                                 }
02217                         }
02218 
02219                         delete(c);
02220                         c = NULL;
02221                         t = JTime();
02222 
02223                 }
02224         }
02225 
02226         delete(server);
02227         server = NULL;
02228 }
02229 
02230 #define TESTMAX 10
02231 bool SocketTester::unitTest() {
02232 
02233         this->addUnitTestLog("Socket test starting...");
02234 
02235 
02236         wait(100);
02237 
02238         printf(".\b"); fflush(stdout);
02239         JSocket* con;
02240 
02241 
02242 
02243         
02244         con = new JSocket("localhost", portnum + 1065, "");
02245 
02246         Collection addresses = con->getLocalIPAddresses();
02247         printf("Found %d local IP addresses:\n\t%s\n\n", addresses.getCount(), (char*) addresses.printListLine("\n\t"));
02248 
02249         Dictionary interfaces = con->getLocalInterfaceAddresses();
02250         printf("Found %d local interfaces:\n\t%s\n\n", interfaces.getCount(), (char*) interfaces.printListLine("\n\t"));
02251 
02252         printf("This computer is '%s' with primary IP address %s\n\n", (char*) con->getLocalHostname(), (char*) con->getLocalIPAddress());
02253         
02254         
02255         
02256 
02257         
02258 
02259         if (con->isConnected()) {
02260                 this->addUnitTestLog("Socket should not be connected at this time...");
02261                 return false;
02262         }
02263 
02264 
02265         if (con->connectNow()) {
02266                 this->addUnitTestLog("Socket should not be connected at this time...");
02267                 return false;
02268         }
02269 
02270 
02271 
02272         if (con->isConnected()) {
02273                 this->addUnitTestLog("Socket should not be connected at this time...");
02274                 return false;
02275         }
02276 
02277         this->addUnitTestLog("Wrong connection test is complete");
02278 
02279         JString localip = con->getLocalIPAddress();
02280 
02281         delete(con);
02282 
02283 
02284 
02285 
02286 
02287 
02288         
02289         con = new JSocket(localip, portnum, "");
02290 
02291 
02292 
02293 
02294         if (con->isConnected()) {
02295                 this->addUnitTestLog("Socket should not be connected at this time...");
02296                 return false;
02297         }
02298 
02299         if (!con->connectNow()) {
02300                 this->addUnitTestLog("Not Connecting to the right connection...");
02301                 return false;
02302         }
02303 
02304         if (!con->isConnected()) {
02305                 this->addUnitTestLog("Not Connected to the right connection...");
02306                 return false;
02307         }
02308         
02309         printf("o\b"); fflush(stdout);
02310 
02311         JString str, str2;
02312         int n, h[TESTMAX], hh[TESTMAX];
02313         for (n = 0; n < TESTMAX; n++) {
02314                 h[n] = 0;
02315                 hh[n] = 0;
02316         }
02317         
02318         
02319         str = "";
02320 
02321         Collection ips = con->getLocalIPAddresses();
02322         this->addUnitTestLog(JString::format("IPs:\n - %s", (char*) ips.printListLine("\n - ")));
02323         Dictionary adaptors = con->getLocalInterfaceAddresses();
02324         this->addUnitTestLog(JString::format("IPs:\n - %s", (char*) adaptors.printListLine("\n - ")));
02325 
02326 
02327         JTime now;
02328         this->addUnitTestLog(JString::format("Socket connected: %s", (char*) now.printTime()));
02329         printf("Performance testing sockets...\n");
02330 
02331         JTime t;
02332         char* buf;
02333         int len2;
02334 
02335         int maxcount = 20;
02336 
02337         #if defined(_WIN32_WCE)
02338                 maxcount = 1;
02339         #endif
02340 
02341         wait(1000);
02342 
02343         for (int kk=0; kk<maxcount; kk++) {
02344                 printf("Pre\b\b\b");
02345                 for (int kkk=0; kkk<1000; kkk++)
02346                   str += "0123456789";
02347                 t = JTime();
02348                 printf("Go\b\b");
02349                 for (n = 0; n < 20; n++) {
02350 
02351                         if (!con->isConnected()) {
02352                                 printf("************  No longer connected!!!  ************\n");
02353                                 this->addUnitTestLog(JString::format("No longer connected %d", n));
02354                                 return false;
02355                         }
02356                         
02357 
02358 
02359 
02360 
02361 
02362 
02363 
02364                         JString str3 = JString((int)str.length()) + JString("\n") + str;
02365                         
02366                         if (con->writeString(str3) <= 0) {
02367                                 printf("************  Unable to write!!!  ************\n");
02368                                 this->addUnitTestLog(JString::format("Unable to write %d", n));
02369                                 con->disconnectNow();
02370                                 delete(con);
02371                         
02372                                 return false;
02373                         }
02374                         
02375         
02376 
02377         
02378                         str2 = con->readln(5000);
02379                         
02380                         int len=str2.toInt();
02381                         if (len <= 0) {
02382                           printf("ERROR1[%d]: %d %d '%s'\n", n, len, (int)str2.length(), (char*) str2);
02383                         this->addUnitTestLog(JString::format("ERROR 1 [%d] read %d chars = %d", n, (int)str2.length(), len));
02384                           return false;
02385                         }
02386                         buf = new char[len+1];
02387                         if ( (len2 = con->read(buf, len, 10000)) < len) {
02388                         this->addUnitTestLog(JString::format("ERROR 2 [%d] read %d != %d ", n, len2, len));
02389                           printf("ERROR2");
02390                           return false;
02391                         } 
02392                         buf[len] = 0;
02393                         str2 = JString(buf);
02394                         delete [] buf;
02395                         buf=NULL;
02396 
02397 
02398                         if (!str.equals(str2)) {
02399                                 printf("************  %d != %d  [%d]  Count: %d  ************\n", str.length(), str2.length(), con->charBufferCount, n);
02400                                 this->addUnitTestLog(JString::format("Not equal", n));
02401                         
02402                                 con->disconnectNow();
02403                                 delete(con);
02404                                 return false;
02405                         }
02406                         
02407 
02408                         
02409                         
02410 
02411                 }
02412 
02413                 now = JTime();
02414                 printf(" Round trip for %d chars: %.3f ms\n", str.length(), ((double)(now-t)/n));
02415         }
02416 
02417         #if defined(_WIN32_WCE)
02418                 maxcount = 1;
02419         #endif
02420 
02421 
02422         delete(con);
02423         con = new JSocket("localhost", portnum, "");
02424         if (!con->connectNow()) {
02425                 this->addUnitTestLog("Socket could not connect 2...");
02426                 return false;
02427         }
02428 
02429         printf("O\b"); fflush(stdout);
02430 
02431 
02432 
02433                 str += "0123456789";
02434                 t = JTime();
02435                 for (n = 0; n < maxcount; n++) {
02436 
02437                         printf("O.\b\b"); fflush(stdout);
02438         
02439                         
02440                         if (!con->isConnected()) {
02441                                 printf("************  No longer connected!!!  ************\n");
02442                                 this->addUnitTestLog(JString::format("No longer 2 %d", n));
02443                                 return false;
02444                         }
02445                         
02446                         if (con->writeln(str) <= 0) {
02447                                 printf("************  Unable to write!!!  ************\n");
02448                                 this->addUnitTestLog(JString::format("unable to write 2 %d", n));
02449                                 con->disconnectNow();
02450                                 delete(con);
02451                         
02452                                 return false;
02453                         }
02454 
02455         
02456 
02457                         printf("Ox\b\b"); fflush(stdout);
02458                         str2 = con->readln(5000);
02459                         printf("Oo\b\b"); fflush(stdout);
02460 
02461                         if (!str.equals(str2)) {
02462                                 printf("************  %d != %d  [%d]  Count: %d  ************\n", str.length(), str2.length(), con->charBufferCount, n);
02463                                 this->addUnitTestLog(JString::format("not equal 2 %d", n));
02464                         
02465                                 con->disconnectNow();
02466                                 delete(con);
02467                                 return false;
02468                         }
02469 
02470         
02471                         delete(con);
02472 
02473 
02474         
02475                         con = new JSocket("localhost", portnum, "");
02476                         if (!con->connectNow()) {
02477                                 this->addUnitTestLog("Socket could not connect 3...");
02478                                 return false;
02479                         }
02480                         printf("OO\b\b"); fflush(stdout);
02481                 }
02482 
02483 
02484 
02485 
02486 
02487         
02488         for (n = 0; n < 5; n++) {
02489 
02490 
02491 
02492                 printf("OO.\b\b\b"); fflush(stdout);
02493                 t = JTime();
02494                 if (!con->isConnected()) {
02495                         printf("************  No longer connected!!!  ************\n");
02496                         this->addUnitTestLog(JString::format("No longer 3 %d", n));
02497                         return false;
02498                 }
02499                 
02500                 if (con->writeln(str) <= 0) {
02501                         printf("************  Unable to write!!!  ************\n");
02502                         this->addUnitTestLog(JString::format("unable to write 3 %d", n));
02503                         con->disconnectNow();
02504                         delete(con);
02505                         wait(1000);
02506                         return false;
02507                 }
02508                 hh[n] = JTime() - t;
02509 
02510                 wait(100);
02511 
02512                 t = JTime();
02513                 printf("OOo\b\b\b"); fflush(stdout);
02514                 str2 = con->readln(10000);
02515                 h[n] = JTime() - t;
02516 
02517                 if (!str.equals(str2)) {
02518 
02519                         printf("************  %d != %d  [%d]  JTime: %d  ************\n", str.length(), str2.length(), con->charBufferCount, n);
02520                         this->addUnitTestLog(JString::format("not equal 3 %d", n));
02521                         wait(1000);
02522                         con->disconnectNow();
02523                         delete(con);
02524                         return false;
02525                 }
02526 
02527                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02528                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02529                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02530                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02531                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02532                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02533                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02534                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02535                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02536                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02537                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02538                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02539                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02540                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02541                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02542                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02543                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02544                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02545                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02546                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02547                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02548                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02549                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02550                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02551                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02552                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02553                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02554                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02555                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02556                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02557                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02558                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02559                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02560                 str += "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
02561 
02562 
02563 
02564 
02565 
02566 
02567 
02568 
02569 
02570 
02571 
02572 
02573         }
02574         printf("OOO\b\b\b"); fflush(stdout);
02575 
02576         con->disconnectNow();
02577         delete(con);
02578 
02579         int tt = 0;
02580         for (n = 0; n < TESTMAX; n++) tt += h[n];
02581         
02582 
02583 
02584         shouldContinue = false;
02585 
02586         wait(100);
02587 
02588         return true;
02589 }
02590 
02591 
02592 
02593 
02594 
02595 
02596 
02597 
02598 
02599 ConnectionProfile::ConnectionProfile(JString profilename) {
02600         name = profilename;
02601         speedUploadBps = 0;
02602         speedDownloadBps = 0;
02603         avgUploadBps = 0;
02604         avgDownloadBps = 0;
02605         maxAvgUploadBps = 0;
02606         maxAvgDownloadBps = 0;
02607         totalUpload = 0;
02608         totalDownload = 0;
02609         totalUploadCount = 0;
02610         totalDownloadCount = 0;
02611         maxConnectionHistory = 10;
02612         isDirectlyConnected = false;
02613 }
02614 
02615 ConnectionProfile::ConnectionProfile(const ConnectionProfile& profile) {
02616         this->name = profile.name;
02617         this->speedUploadBps = profile.speedUploadBps;
02618         this->speedDownloadBps = profile.speedDownloadBps;
02619         this->avgUploadBps = profile.avgUploadBps;
02620         this->avgDownloadBps = profile.avgDownloadBps;
02621         this->maxAvgUploadBps = profile.maxAvgUploadBps;
02622         this->maxAvgDownloadBps = profile.maxAvgDownloadBps;
02623         this->totalUpload = profile.totalUpload;
02624         this->totalDownload = profile.totalDownload;
02625         this->totalUploadCount = profile.totalUploadCount;
02626         this->totalDownloadCount = profile.totalDownloadCount;
02627         this->uploadHistory = profile.uploadHistory;
02628         this->downloadHistory = profile.downloadHistory;
02629 }
02630 
02631 const ConnectionProfile& ConnectionProfile::operator = (const ConnectionProfile& profile) {
02632         this->name = profile.name;
02633         this->speedUploadBps = profile.speedUploadBps;
02634         this->speedDownloadBps = profile.speedDownloadBps;
02635         this->avgUploadBps = profile.avgUploadBps;
02636         this->avgDownloadBps = profile.avgDownloadBps;
02637         this->maxAvgUploadBps = profile.maxAvgUploadBps;
02638         this->maxAvgDownloadBps = profile.maxAvgDownloadBps;
02639         this->totalUpload = profile.totalUpload;
02640         this->totalDownload = profile.totalDownload;
02641         this->totalUploadCount = profile.totalUploadCount;
02642         this->totalDownloadCount = profile.totalDownloadCount;
02643         this->uploadHistory = profile.uploadHistory;
02644         this->downloadHistory = profile.downloadHistory;
02645         return *this;
02646 }
02647 
02648 
02649 ConnectionProfile::ConnectionProfile(XMLNode* node) {
02650         speedUploadBps = 0;
02651         speedDownloadBps = 0;
02652         avgUploadBps = 0;
02653         avgDownloadBps = 0;
02654         maxAvgUploadBps = 0;
02655         maxAvgDownloadBps = 0;
02656         totalUpload = 0;
02657         totalDownload = 0;
02658         totalUploadCount = 0;
02659         totalDownloadCount = 0;
02660         maxConnectionHistory = 10;
02661         isDirectlyConnected = false;
02662         if (!fromXML(node)) {}
02663 }
02664 
02665 Object* ConnectionProfile::clone() const {
02666         ConnectionProfile* profile = new ConnectionProfile();
02667 
02668         profile->name = this->name;
02669         profile->speedUploadBps = this->speedUploadBps;
02670         profile->speedDownloadBps = this->speedDownloadBps;
02671         profile->avgUploadBps = this->avgUploadBps;
02672         profile->avgDownloadBps = this->avgDownloadBps;
02673         profile->maxAvgUploadBps = this->maxAvgUploadBps;
02674         profile->maxAvgDownloadBps = this->maxAvgDownloadBps;
02675         profile->totalUpload = this->totalUpload;
02676         profile->totalDownload = this->totalDownload;
02677         profile->totalUploadCount = this->totalUploadCount;
02678         profile->totalDownloadCount = this->totalDownloadCount;
02679 
02680 
02681         return profile;
02682 }
02683 
02684 bool ConnectionProfile::equals(const Object* obj) const {
02685         return (this->name.equalsIgnoreCase(((ConnectionProfile*)obj)->name));
02686 }
02687 
02688 bool ConnectionProfile::fromXML(XMLNode* node) {
02689         if (node == NULL)
02690                 return false;
02691 
02692         if (!node->getTag().equalsIgnoreCase("connectionprofile"))
02693                 return false;
02694 
02695         name = node->getAttribute("name");
02696         speedUploadBps = node->getAttribute("speeduploadbps").toLong();
02697         speedDownloadBps = node->getAttribute("speeddownloadbps").toLong();
02698         avgUploadBps = node->getAttribute("avguploadbps").toLong();
02699         avgDownloadBps = node->getAttribute("avgdownloadbps").toLong();
02700         maxAvgUploadBps = node->getAttribute("maxavguploadbps").toLong();
02701         maxAvgDownloadBps = node->getAttribute("maxavgdownloadbps").toLong();
02702         totalUpload = node->getAttribute("totalupload").toDouble();
02703         totalDownload = node->getAttribute("totaldownload").toDouble();
02704         totalUploadCount = node->getAttribute("totaluploadcount").toLong();
02705         totalDownloadCount = node->getAttribute("totaldownloadcount").toLong();
02706 
02707         return true;
02708 }
02709 
02710 JString ConnectionProfile::toXML() {
02711         JString up = JString(totalUpload);
02712         JString down = JString(totalDownload);
02713         if (isDirectlyConnected)
02714                 return JString::format("<connectionprofile name=\"%s\" speeduploadbps=\"%ld\" speeddownloadbps=\"%ld\" avguploadbps=\"%ld\" avgdownloadbps=\"%ld\" maxavguploadbps=\"%ld\" maxavgdownloadbps=\"%ld\"  totalupload=\"%s\" totaldownload=\"%s\"  totaluploadcount=\"%ld\" totaldownloadcount=\"%ld\" maxhistory=\"%d\" direct=\"yes\" />",
02715                         (char*) name.xmlStringEncode(), speedUploadBps, speedDownloadBps, avgUploadBps, avgDownloadBps, maxAvgUploadBps, maxAvgDownloadBps, (char*) up, (char*) down, totalUploadCount, totalDownloadCount, maxConnectionHistory);
02716         else
02717                 return JString::format("<connectionprofile name=\"%s\" speeduploadbps=\"%ld\" speeddownloadbps=\"%ld\" avguploadbps=\"%ld\" avgdownloadbps=\"%ld\" maxavguploadbps=\"%ld\" maxavgdownloadbps=\"%ld\"  totalupload=\"%s\" totaldownload=\"%s\" totaluploadcount=\"%ld\" totaldownloadcount=\"%ld\" maxhistory=\"%d\" direct=\"no\" />",
02718                         (char*) name.xmlStringEncode(), speedUploadBps, speedDownloadBps, avgUploadBps, avgDownloadBps, maxAvgUploadBps, maxAvgDownloadBps, (char*) up, (char*) down, totalUploadCount, totalDownloadCount, maxConnectionHistory);
02719 }
02720 
02721 
02722 bool ConnectionProfile::setSpeed(long upbps, long downbps) {
02723         speedUploadBps = upbps;
02724         speedDownloadBps = downbps;
02725         return true;
02726 }
02727 
02728 bool ConnectionProfile::addDataStat(long upbytes, long downbytes, const JTime& time) {
02729         if (upbytes > 0) {
02730                 totalUploadCount++;
02731                 totalUpload += upbytes;
02732                 uploadHistory.put(time, new JString(upbytes));
02733                 while (uploadHistory.getCount() > maxConnectionHistory) {
02734                         
02735                         uploadHistory.removeOldest();
02736                 }
02737         }
02738         if (downbytes > 0) {
02739                 totalDownloadCount++;
02740                 totalDownload += downbytes;
02741                 downloadHistory.put(time, new JString(downbytes));
02742                 while (downloadHistory.getCount() > maxConnectionHistory) {
02743                         
02744                         downloadHistory.removeOldest();
02745                 }
02746         }
02747         return true;
02748 }
02749 
02750 JTime ConnectionProfile::getLastActivity() {
02751         JTime up = uploadHistory.getLastTime();
02752         JTime down = downloadHistory.getLastTime();
02753         if ( (!up.isValid()) && (!down.isValid()) ) {
02754                 JTime res;
02755                 res.setInvalid();
02756                 return res;
02757         }
02758         else if (!up.isValid())
02759                 return down;
02760         else if (!down.isValid())
02761                 return up;
02762         else {
02763                 if (up - down > 0)
02764                         return up;
02765                 else
02766                         return down;
02767         }
02768 }
02769 
02770 long ConnectionProfile::getSpeedUpload() {
02771         recalc();
02772         return speedUploadBps;
02773 }
02774 
02775 long ConnectionProfile::getSpeedDownload() {
02776         recalc();
02777         return speedDownloadBps;
02778 }
02779 
02780 
02781 long ConnectionProfile::getAvgUpload() {
02782         recalc();
02783         return avgUploadBps;
02784 }
02785 
02786 long ConnectionProfile::getAvgDownload() {
02787         recalc();
02788         return avgDownloadBps;
02789 }
02790 
02791 
02792 long ConnectionProfile::getMaxAvgUpload() {
02793         recalc();
02794         return maxAvgUploadBps;
02795 }
02796 
02797 long ConnectionProfile::getMaxAvgDownload() {
02798         recalc();
02799         return maxAvgDownloadBps;
02800 }
02801 
02802 double ConnectionProfile::getTotalUpload() {
02803         recalc();
02804         return totalUpload;
02805 }
02806 
02807 double ConnectionProfile::getTotalDownload() {
02808         recalc();
02809         return totalDownload;
02810 }
02811 
02812 long ConnectionProfile::getTotalUploadCount() {
02813         return totalUploadCount;
02814 }
02815 
02816 long ConnectionProfile::getTotalDownloadCount() {
02817         return totalDownloadCount;
02818 }
02819 
02820 bool ConnectionProfile::recalc() {
02821 
02822         JTime now;
02823         JTime t;
02824         int n;
02825         double totalup = 0;
02826         double totaldown = 0;
02827 
02828         if (uploadHistory.getCount() > 0) {
02829                 t = uploadHistory.getFirstTime();
02830                 double upduration = now.microDifference(t) / 1000000.0;
02831                 if (upduration > 0) {
02832                         for (n=0; n<uploadHistory.getCount(); n++)
02833                                 totalup += ((JString*)uploadHistory.get(n))->toLong();
02834                         avgUploadBps = (long) (totalup / upduration);
02835                         if (avgUploadBps > maxAvgUploadBps)
02836                                 maxAvgUploadBps = avgUploadBps;
02837                 }
02838         }
02839         if (downloadHistory.getCount() > 0) {
02840                 t = downloadHistory.getFirstTime();
02841                 double downduration = now.microDifference(t) / 1000000.0;
02842                 if (downduration > 0) {
02843                         for (n=0; n<downloadHistory.getCount(); n++)
02844                                 totaldown += ((JString*)downloadHistory.get(n))->toLong();
02845                         avgDownloadBps = (long) (totaldown / downduration);
02846                         if (avgDownloadBps > maxAvgDownloadBps)
02847                                 maxAvgDownloadBps = avgDownloadBps;
02848                 }
02849         }
02850         return true;
02851 }
02852 
02853 
02854 JString ConnectionProfile::getSpeedString() {
02855         return JString::bytifyRates(speedUploadBps, speedDownloadBps);
02856 }
02857 
02858 JString ConnectionProfile::getRateString() {
02859         recalc();
02860         return JString::bytifyRates(avgUploadBps, avgDownloadBps);
02861 }
02862 
02863 JString ConnectionProfile::getMaxRateString() {
02864         recalc();
02865         return JString::bytifyRates(maxAvgUploadBps, maxAvgDownloadBps);
02866 }
02867 
02868 JString ConnectionProfile::getTotalString() {
02869         return JString::bytifySizes(totalUpload, totalDownload);
02870 }
02871 
02872 
02873 JString ConnectionProfile::print() {
02874         JTime lastAct = getLastActivity();
02875         
02876         if (!isDirectlyConnected) {
02877                 return JString::format("Connection Profile: %s\n  Speed:   %s\n  Rate:    %s\n  MaxRate: %s\n  Total:   %s\n",
02878                         (char*) name,
02879                         (char*) getSpeedString(),
02880                         (char*) getRateString(),
02881                         (char*) getMaxRateString(),
02882                         (char*) getTotalString());
02883         }
02884         else {
02885                 return JString::format("Direct Connection Profile: %s\n  Rate:    %s\n  MaxRate: %s\n  Total:   %s\n",
02886                         (char*) name,
02887                         (char*) getRateString(),
02888                         (char*) getMaxRateString(),
02889                         (char*) getTotalString());
02890         }
02891 
02892 }
02893 
02894 JString ConnectionProfile::toHTML() {
02895         JTime lastAct = getLastActivity();
02896         
02897         if (!isDirectlyConnected) {
02898                 return JString::format("Connection Profile: %s\n<br>  Speed:   %s\n<br>  Rate:    %s\n<br>  MaxRate: %s\n<br>  Total:   %s\n<br>",
02899                         (char*) name,
02900                         (char*) getSpeedString(),
02901                         (char*) getRateString(),
02902                         (char*) getMaxRateString(),
02903                         (char*) getTotalString());
02904         }
02905         else {
02906                 return JString::format("Direct Connection Profile: %s\n<br>  Rate:    %s\n<br>  MaxRate: %s\n<br>  Total:   %s\n<br>",
02907                         (char*) name,
02908                         (char*) getRateString(),
02909                         (char*) getMaxRateString(),
02910                         (char*) getTotalString());
02911         }
02912 }
02913 
02914 
02915 
02916 
02917 
02918 
02919 
02920 }