sys.cpp
上传用户:chn_coc
上传日期:2007-12-20
资源大小:563k
文件大小:18k
源码类别:

P2P编程

开发平台:

Windows_Unix

  1. // ------------------------------------------------ // File : sys.cpp // Date: 4-apr-2002 // Author: giles // Desc:  // Sys is a base class for all things systemy, like starting threads, creating sockets etc.. // Lock is a very basic cross platform CriticalSection class
  2. // SJIS-UTF8 conversion by ???? // // (c) 2002 peercast.org // ------------------------------------------------ // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the // GNU General Public License for more details. // ------------------------------------------------ #include "common.h" #include "sys.h" #include "socket.h" #include "gnutella.h" #include <stdlib.h> #include <time.h>
  3. #include "jis.h"
  4. // -----------------------------------
  5. #define isSJIS(a,b) ((a >= 0x81 && a <= 0x9f || a >= 0xe0 && a<=0xfc) && (b >= 0x40 && b <= 0x7e || b >= 0x80 && b<=0xfc))
  6. #define isEUC(a) (a >= 0xa1 && a <= 0xfe)
  7. #define isASCII(a) (a <= 0x7f) 
  8. #define isPLAINASCII(a) (((a >= '0') && (a <= '9')) || ((a >= 'a') && (a <= 'z')) || ((a >= 'A') && (a <= 'Z')))
  9. #define isUTF8(a,b) ((a & 0xc0) == 0xc0 && (b & 0x80) == 0x80 )
  10. #define isESCAPE(a,b) ((a == '&') && (b == '#'))
  11. #define isHTMLSPECIAL(a) ((a == '&') || (a == '"') || (a == ''') || (a == '<') || (a == '>'))
  12. // ----------------------------------- const char *LogBuffer::logTypes[]= { "", "DBUG", "EROR", "GNET", "CHAN", }; // ----------------------------------- // base64 encode/decode taken from ices2 source..  static char base64table[64] = {     'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',     'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',     'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',     'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' }; #if 0 // ----------------------------------- static char *util_base64_encode(char *data) {     int len = strlen(data);     char *out = malloc(len*4/3 + 4);     char *result = out;     int chunk;     while(len > 0) {         chunk = (len >3)?3:len;         *out++ = base64table[(*data & 0xFC)>>2];         *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)];         switch(chunk) {             case 3:                 *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)];                 *out++ = base64table[(*(data+2)) & 0x3F];                 break;             case 2:                 *out++ = base64table[((*(data+1) & 0x0F)<<2)];                 *out++ = '=';                 break;             case 1:                 *out++ = '=';                 *out++ = '=';                 break;         }         data += chunk;         len -= chunk;     }     return result; } #endif // ----------------------------------- static int base64chartoval(char input) {     if(input >= 'A' && input <= 'Z')         return input - 'A';     else if(input >= 'a' && input <= 'z')         return input - 'a' + 26;     else if(input >= '0' && input <= '9')         return input - '0' + 52;     else if(input == '+')         return 62;     else if(input == '/')         return 63;     else if(input == '=')         return -1;     else         return -2; } // ----------------------------------- static char *util_base64_decode(char *input) { return NULL; } // ------------------------------------------ Sys::Sys() { idleSleepTime = 10; logBuf = new LogBuffer(1000,100);
  13. numThreads=0; } // ------------------------------------------ void Sys::sleepIdle() { sleep(idleSleepTime); } // ------------------------------------------ void Host::toResolvedName(char *str) { char hostName[128]; if (ClientSocket::getHostname(hostName,ip)) sprintf(str,"%s:%d",hostName,port); else toStr(str); } // ------------------------------------------ bool Host::isLocalhost() {
  14. return loopbackIP() || (ip == ClientSocket::getIP(NULL));  } // ------------------------------------------ void Host::fromStrName(const char *str, int p) { if (!strlen(str)) { port = 0; ip = 0; return; } char name[128]; strcpy(name,str); port = p; char *pp = strstr(name,":"); if (pp) { port = atoi(pp+1); pp[0] = 0; } ip = ClientSocket::getIP(name); } // ------------------------------------------ void Host::fromStrIP(const char *str, int p) { unsigned int ipb[4]; unsigned int ipp; if (strstr(str,":")) { if (sscanf(str,"%03d.%03d.%03d.%03d:%d",&ipb[0],&ipb[1],&ipb[2],&ipb[3],&ipp) == 5) { ip = ((ipb[0]&0xff) << 24) | ((ipb[1]&0xff) << 16) | ((ipb[2]&0xff) << 8) | ((ipb[3]&0xff)); port = ipp; }else { ip = 0; port = 0; } }else{ port = p; if (sscanf(str,"%03d.%03d.%03d.%03d",&ipb[0],&ipb[1],&ipb[2],&ipb[3]) == 4) ip = ((ipb[0]&0xff) << 24) | ((ipb[1]&0xff) << 16) | ((ipb[2]&0xff) << 8) | ((ipb[3]&0xff)); else ip = 0; } } // ----------------------------------- bool Host::isMemberOf(Host &h) { if (h.ip==0) return false;     if( h.ip0() != 255 && ip0() != h.ip0() )         return false;     if( h.ip1() != 255 && ip1() != h.ip1() )         return false;     if( h.ip2() != 255 && ip2() != h.ip2() )         return false;     if( h.ip3() != 255 && ip3() != h.ip3() )         return false; /* removed for endieness compatibility for(int i=0; i<4; i++) if (h.ipByte[i] != 255) if (ipByte[i] != h.ipByte[i]) return false; */ return true; } // ----------------------------------- char *trimstr(char *s1) { while (*s1) { if ((*s1 == ' ') || (*s1 == 't')) s1++; else break; } char *s = s1; s1 = s1+strlen(s1); while (*--s1) if ((*s1 != ' ') && (*s1 != 't')) break; s1[1] = 0; return s; } // ----------------------------------- char *stristr(const char *s1, const char *s2) { while (*s1) { if (TOUPPER(*s1) == TOUPPER(*s2)) { const char *c1 = s1; const char *c2 = s2; while (*c1 && *c2) { if (TOUPPER(*c1) != TOUPPER(*c2)) break; c1++; c2++; } if (*c2==0) return (char *)s1; } s1++; } return NULL; } // ----------------------------------- bool String::isValidURL() { return (strnicmp(data,"http://",7)==0) || (strnicmp(data,"mailto:",7)==0); } // ----------------------------------- void String::setFromTime(unsigned int t) { char *p = ctime((time_t*)&t); if (p) strcpy(data,p); else strcpy(data,"-"); type = T_ASCII; } // ----------------------------------- void String::setFromStopwatch(unsigned int t) { unsigned int sec,min,hour,day; sec = t%60; min = (t/60)%60; hour = (t/3600)%24; day = (t/86400); if (day) sprintf(data,"%d day, %d hour",day,hour); else if (hour) sprintf(data,"%d hour, %d min",hour,min); else if (min) sprintf(data,"%d min, %d sec",min,sec); else if (sec) sprintf(data,"%d sec",sec); else sprintf(data,"-"); type = T_ASCII; } // ----------------------------------- void String::setFromString(const char *str, TYPE t) { int cnt=0; bool quote=false; while (*str) { bool add=true; if (*str == '"') { if (quote)  break; else  quote = true; add = false; }else if (*str == ' ') { if (!quote) { if (cnt) break; else add = false; } } if (add) { data[cnt++] = *str++; if (cnt >= (MAX_LEN-1)) break; }else str++; } data[cnt] = 0; type = t; } // ----------------------------------- int String::base64WordToChars(char *out,const char *input) { char *start = out; signed char vals[4];     vals[0] = base64chartoval(*input++);     vals[1] = base64chartoval(*input++);     vals[2] = base64chartoval(*input++);     vals[3] = base64chartoval(*input++);     if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1)  return 0;     *out++ = vals[0]<<2 | vals[1]>>4;     if(vals[2] >= 0)         *out++ = ((vals[1]&0x0F)<<4) | (vals[2]>>2);     else         *out++ = 0;     if(vals[3] >= 0)         *out++ = ((vals[2]&0x03)<<6) | (vals[3]);     else         *out++ = 0; return out-start; } // ----------------------------------- void String::BASE642ASCII(const char *input) { char *out = data;     int len = strlen(input);     while(len >= 4)  { out += base64WordToChars(out,input); input += 4;         len -= 4;     }     *out = 0; }
  15. // -----------------------------------
  16. void String::UNKNOWN2UNICODE(const char *in,bool safe)
  17. {
  18. MemoryStream utf8(data,MAX_LEN-1);
  19. unsigned char c;
  20. unsigned char d;
  21. while (c = *in++)
  22. {
  23. d = *in;
  24. if (isUTF8(c,d)) // utf8 encoded 
  25. {
  26. int numChars=0;
  27. int i;
  28. for(i=0; i<6; i++)
  29. {
  30. if (c & (0x80>>i))
  31. numChars++;
  32. else
  33. break;
  34. }
  35. utf8.writeChar(c);
  36. for(i=0; i<numChars-1; i++)
  37. utf8.writeChar(*in++);
  38. }
  39. else if(isSJIS(c,d)) // shift_jis
  40. {
  41. utf8.writeUTF8(JISConverter::sjisToUnicode((c<<8 | d)));
  42. in++;
  43. }
  44. else if(isEUC(c) && isEUC(d)) // euc-jp
  45. {
  46. utf8.writeUTF8(JISConverter::eucToUnicode((c<<8 | d)));
  47. in++;
  48. }
  49. else if (isESCAPE(c,d)) // html escape tags &#xx;
  50. {
  51. in++;
  52. char code[16];
  53. char *cp = code;
  54. while (c=*in++) 
  55. {
  56. if (c!=';')
  57. *cp++ = c;
  58. else
  59. break;
  60. }
  61. *cp = 0;
  62. utf8.writeUTF8(strtoul(code,NULL,10));
  63. }
  64. else if (isPLAINASCII(c)) // plain ascii : a-z 0-9 etc..
  65. {
  66. utf8.writeUTF8(c);
  67. }
  68. else if (isHTMLSPECIAL(c) && safe)
  69. {
  70. const char *str = NULL;
  71. if (c == '&') str = "&amp;";
  72. else if (c == '"') str = "&quot;";
  73. else if (c == ''') str = "&#039;";
  74. else if (c == '<') str = "&lt;";
  75. else if (c == '>') str = "&gt;";
  76. else str = "?";
  77. utf8.writeString(str);
  78. }
  79. else
  80. {
  81. utf8.writeUTF8(c);
  82. }
  83. if (utf8.pos >= (MAX_LEN-10))
  84. break;
  85. }
  86. utf8.writeChar(0); // null terminate
  87. }
  88. // -----------------------------------
  89. void String::ASCII2HTML(const char *in)
  90. {
  91. char *op = data;
  92. char *oe = data+MAX_LEN-10;
  93. unsigned char c;
  94. const char *p = in;
  95. while (c = *p++)
  96. {
  97. if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))
  98. {
  99. *op++ = c;
  100. }else
  101. {
  102. sprintf(op,"&#x%02X;",(int)c);
  103. op+=6;
  104. }
  105. if (op >= oe)
  106. break;
  107. }
  108. *op = 0;
  109. }
  110. // ----------------------------------- void String::ASCII2ESC(const char *in, bool safe) { char *op = data; char *oe = data+MAX_LEN-10; const char *p = in; unsigned char c; while (c = *p++) { if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) *op++ = c; else { *op++ = '%'; if (safe) *op++ = '%'; *op=0; sprintf(op,"%02X",(int)c); op+=2; } if (op >= oe) break; } *op=0; } // ----------------------------------- void String::HTML2ASCII(const char *in) { unsigned char c; char *o = data; char *oe = data+MAX_LEN-10; const char *p = in; while (c = *p++) { if ((c == '&') && (p[0] == '#')) { p++; char code[8]; char *cp = code; char ec = *p++; // hex/dec while (c=*p++)  { if (c!=';') *cp++ = c; else break; } *cp = 0; c = (unsigned char)strtoul(code,NULL,ec=='x'?16:10); } *o++ = c; if (o >= oe) break; } *o=0; } // -----------------------------------
  111. void String::HTML2UNICODE(const char *in)
  112. {
  113. MemoryStream utf8(data,MAX_LEN-1);
  114. unsigned char c;
  115. while (c = *in++)
  116. {
  117. if ((c == '&') && (*in == '#'))
  118. {
  119. in++;
  120. char code[16];
  121. char *cp = code;
  122. char ec = *in++; // hex/dec
  123. while (c=*in++) 
  124. {
  125. if (c!=';')
  126. *cp++ = c;
  127. else
  128. break;
  129. }
  130. *cp = 0;
  131. utf8.writeUTF8(strtoul(code,NULL,ec=='x'?16:10));
  132. }else
  133. utf8.writeUTF8(c);
  134. if (utf8.pos >= (MAX_LEN-10))
  135. break;
  136. }
  137. utf8.writeUTF8(0);
  138. }
  139. // ----------------------------------- void String::ESC2ASCII(const char *in) { unsigned char c; char *o = data; char *oe = data+MAX_LEN-10; const char *p = in; while (c = *p++) { if (c == '+') c = ' '; else if (c == '%') { if (p[0] == '%') p++; char hi = TOUPPER(p[0]); char lo = TOUPPER(p[1]); c = (TONIBBLE(hi)<<4) | TONIBBLE(lo); p+=2; } *o++ = c; if (o >= oe) break; } *o=0; } // ----------------------------------- void String::ASCII2META(const char *in, bool safe) { char *op = data; char *oe = data+MAX_LEN-10; const char *p = in; unsigned char c; while (c = *p++) { switch (c) { case '%': if (safe) *op++='%'; break; case ';': c = ':'; break; } *op++=c; if (op >= oe) break; } *op=0; } // ----------------------------------- void String::convertTo(TYPE t) { if (t != type) { String tmp = *this; // convert to ASCII switch (type) { case T_UNKNOWN: case T_ASCII: break; case T_HTML: tmp.HTML2ASCII(data); break; case T_ESC: case T_ESCSAFE: tmp.ESC2ASCII(data); break; case T_META: case T_METASAFE: break; case T_BASE64: tmp.BASE642ASCII(data); break; } // convert to new format switch (t) { case T_UNKNOWN: case T_ASCII: strcpy(data,tmp.data); break; case T_UNICODE:
  140. UNKNOWN2UNICODE(tmp.data,false);
  141. break;
  142. case T_UNICODESAFE:
  143. UNKNOWN2UNICODE(tmp.data,true);
  144. break;
  145. case T_HTML: ASCII2HTML(tmp.data); break; case T_ESC: ASCII2ESC(tmp.data,false); break; case T_ESCSAFE: ASCII2ESC(tmp.data,true); break; case T_META: ASCII2META(tmp.data,false); break; case T_METASAFE: ASCII2META(tmp.data,true); break; } type = t; } } // ----------------------------------- void LogBuffer::write(const char *str, TYPE t) { lock.on(); unsigned int len = strlen(str); int cnt=0; while (len) { unsigned int rlen = len; if (rlen > (lineLen-1)) rlen = lineLen-1; int i = currLine % maxLines; int bp = i*lineLen; strncpy(&buf[bp],str,rlen); buf[bp+rlen] = 0; if (cnt==0) { times[i] = sys->getTime(); types[i] = t; }else { times[i] = 0; types[i] = T_NONE; } currLine++; str += rlen; len -= rlen; cnt++; } lock.off(); } // ----------------------------------- char *getCGIarg(const char *str, const char *arg) { if (!str) return NULL; char *s = strstr(str,arg); if (!s) return NULL; s += strlen(arg); return s; } // ----------------------------------- bool cmpCGIarg(char *str, char *arg, char *value) { if ((!str) || (!strlen(value))) return false; if (strnicmp(str,arg,strlen(arg)) == 0)
  146. { str += strlen(arg); return strncmp(str,value,strlen(value))==0;
  147. }else
  148. return false; } // ----------------------------------- bool hasCGIarg(char *str, char *arg) { if (!str) return false; char *s = strstr(str,arg); if (!s) return false; return true; } // --------------------------- void GnuID::encode(Host *h, const char *salt1, const char *salt2, unsigned char salt3) { int s1=0,s2=0; for(int i=0; i<16; i++) { unsigned char ipb = id[i]; // encode with IP address  if (h) ipb ^= ((unsigned char *)&h->ip)[i&3]; // add a bit of salt  if (salt1) { if (salt1[s1]) ipb ^= salt1[s1++]; else s1=0; } // and some more if (salt2) { if (salt2[s2]) ipb ^= salt2[s2++]; else s2=0; } // plus some pepper ipb ^= salt3; id[i] = ipb; } } // --------------------------- void GnuID::toStr(char *str) { str[0] = 0; for(int i=0; i<16; i++) { char tmp[8]; unsigned char ipb = id[i]; sprintf(tmp,"%02X",ipb); strcat(str,tmp); } } // --------------------------- void GnuID::fromStr(const char *str) { clear(); if (strlen(str) < 32) return; char buf[8]; buf[2] = 0; for(int i=0; i<16; i++) { buf[0] = str[i*2]; buf[1] = str[i*2+1]; id[i] = (unsigned char)strtoul(buf,NULL,16); } } // --------------------------- void GnuID::generate(unsigned char flags) { clear(); for(int i=0; i<16; i++) id[i] = sys->rnd();
  149. id[0] = flags; } // --------------------------- unsigned char GnuID::getFlags() { return id[0]; } // --------------------------- GnuIDList::GnuIDList(int max) :ids(new GnuID[max]) { maxID = max; for(int i=0; i<maxID; i++) ids[i].clear(); } // --------------------------- GnuIDList::~GnuIDList() { delete [] ids; } // --------------------------- bool GnuIDList::contains(GnuID &id) { for(int i=0; i<maxID; i++) if (ids[i].isSame(id)) return true; return false; } // --------------------------- int GnuIDList::numUsed() { int cnt=0; for(int i=0; i<maxID; i++) if (ids[i].storeTime) cnt++; return cnt; } // --------------------------- unsigned int GnuIDList::getOldest() { unsigned int t=(unsigned int)-1; for(int i=0; i<maxID; i++) if (ids[i].storeTime) if (ids[i].storeTime < t) t = ids[i].storeTime; return t; } // --------------------------- void GnuIDList::add(GnuID &id) {
  150. unsigned int minTime = (unsigned int) -1; int minIndex = 0; // find same or oldest for(int i=0; i<maxID; i++)
  151. {
  152. if (ids[i].isSame(id))
  153. {
  154. ids[i].storeTime = sys->getTime();
  155. return;
  156. } if (ids[i].storeTime <= minTime) { minTime = ids[i].storeTime; minIndex = i; }
  157. } ids[minIndex] = id; ids[minIndex].storeTime = sys->getTime(); } // --------------------------- void GnuIDList::clear() { for(int i=0; i<maxID; i++) ids[i].clear(); }
  158. // ---------------------------
  159. void LogBuffer::dumpHTML(Stream &out)
  160. {
  161. lock.on();
  162. unsigned int nl = currLine;
  163. unsigned int sp = 0;
  164. if (nl > maxLines)
  165. {
  166. nl = maxLines-1;
  167. sp = (currLine+1)%maxLines;
  168. }
  169. String tim,str;
  170. if (nl)
  171. {
  172. for(unsigned int i=0; i<nl; i++)
  173. {
  174. unsigned int bp = sp*lineLen;
  175. if (types[sp])
  176. {
  177. tim.setFromTime(times[sp]);
  178. out.writeString(tim.cstr());
  179. out.writeString(" <b>[");
  180. out.writeString(getTypeStr(types[sp]));
  181. out.writeString("]</b> ");
  182. }
  183. str.set(&buf[bp]);
  184. str.convertTo(String::T_HTML);
  185. out.writeString(str.cstr());
  186. out.writeString("<br>");
  187. sp++;
  188. sp %= maxLines;
  189. }
  190. }
  191. lock.off();
  192. }
  193. // ---------------------------
  194. void ThreadInfo::shutdown()
  195. {
  196. active = false;
  197. //sys->waitThread(this);
  198. }