reSIProcate/stack  9694
DateCategory.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include <time.h>
00006 
00007 #include "resip/stack/DateCategory.hxx"
00008 #include "resip/stack/Transport.hxx"
00009 #include "rutil/Data.hxx"
00010 #include "rutil/DnsUtil.hxx"
00011 #include "rutil/Logger.hxx"
00012 #include "rutil/ParseBuffer.hxx"
00013 #include "rutil/Socket.hxx"
00014 //#include "rutil/WinLeakCheck.hxx"  // not compatible with placement new used below
00015 
00016 using namespace resip;
00017 using namespace std;
00018 
00019 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00020 
00021 //====================
00022 // Date
00023 //====================
00024 
00025 Data resip::DayOfWeekData[] =
00026 {
00027    "Sun",
00028    "Mon",
00029    "Tue",
00030    "Wed",
00031    "Thu",
00032    "Fri",
00033    "Sat"
00034 };
00035 
00036 Data resip::MonthData[] =
00037 {
00038    "Jan",
00039    "Feb",
00040    "Mar",
00041    "Apr",
00042    "May",
00043    "Jun",
00044    "Jul",
00045    "Aug",
00046    "Sep",
00047    "Oct",
00048    "Nov",
00049    "Dec"
00050 };
00051 
00052 
00053 DateCategory::DateCategory()
00054    : ParserCategory(),
00055      mDayOfWeek(Sun),
00056      mDayOfMonth(),
00057      mMonth(Jan),
00058      mYear(0),
00059      mHour(0),
00060      mMin(0),
00061      mSec(0)
00062 {
00063    time_t now;
00064    time(&now);
00065    if (now == ((time_t)-1))
00066    {
00067       int e = getErrno();
00068       DebugLog (<< "Failed to get time: " << strerror(e));
00069       Transport::error(e);
00070       return;
00071    }
00072    
00073    setDatetime(now);
00074 }
00075 
00076 DateCategory::DateCategory(time_t datetime)
00077    : ParserCategory(),
00078      mDayOfWeek(Sun),
00079      mDayOfMonth(),
00080      mMonth(Jan),
00081      mYear(0),
00082      mHour(0),
00083      mMin(0),
00084      mSec(0)
00085 {
00086    setDatetime(datetime);
00087 }
00088 
00089 DateCategory::DateCategory(const HeaderFieldValue& hfv, 
00090                            Headers::Type type,
00091                            PoolBase* pool)
00092    : ParserCategory(hfv, type, pool),
00093      mDayOfWeek(Sun),
00094      mDayOfMonth(),
00095      mMonth(Jan),
00096      mYear(0),
00097      mHour(0),
00098      mMin(0),
00099      mSec(0)
00100 {}
00101 
00102 DateCategory::DateCategory(const DateCategory& rhs,
00103                            PoolBase* pool)
00104    : ParserCategory(rhs, pool),
00105      mDayOfWeek(rhs.mDayOfWeek),
00106      mDayOfMonth(rhs.mDayOfMonth),
00107      mMonth(rhs.mMonth),
00108      mYear(rhs.mYear),
00109      mHour(rhs.mHour),
00110      mMin(rhs.mMin),
00111      mSec(rhs.mSec)
00112 {}
00113 
00114 DateCategory&
00115 DateCategory::operator=(const DateCategory& rhs)
00116 {
00117    if (this != &rhs)
00118    {
00119       ParserCategory::operator=(rhs);
00120       mDayOfWeek = rhs.mDayOfWeek;
00121       mDayOfMonth = rhs.mDayOfMonth;
00122       mMonth = rhs.mMonth;
00123       mYear = rhs.mYear;
00124       mHour = rhs.mHour;
00125       mMin = rhs.mMin;
00126       mSec = rhs.mSec;
00127    }
00128    return *this;
00129 }
00130 
00131 bool 
00132 DateCategory::setDatetime(time_t datetime)
00133 {
00134    struct tm gmt;
00135 #if defined(WIN32) || defined(__sun)
00136    struct tm *gmtp = gmtime(&datetime);
00137    if (gmtp == 0)
00138    {
00139         int e = getErrno();
00140         DebugLog (<< "Failed to convert to gmt: " << strerror(e));
00141         Transport::error(e);
00142         return false;
00143    }
00144    memcpy(&gmt,gmtp,sizeof(gmt));
00145 #else
00146   if (gmtime_r(&datetime, &gmt) == 0)
00147   {
00148      int e = getErrno();
00149      DebugLog (<< "Failed to convert to gmt: " << strerror(e));
00150      Transport::error(e);
00151      return false;
00152   }
00153 #endif
00154 
00155    mDayOfWeek = static_cast<DayOfWeek>(gmt.tm_wday);
00156    mDayOfMonth = gmt.tm_mday;
00157    mMonth = static_cast<Month>(gmt.tm_mon);
00158    mYear = gmt.tm_year + 1900;
00159    mHour = gmt.tm_hour;
00160    mMin = gmt.tm_min;
00161    mSec = gmt.tm_sec;
00162    DebugLog (<< "Set date: day=" << mDayOfWeek 
00163              << " month=" << mMonth
00164              << " year=" << mYear
00165              << " " << mHour << ":" << mMin << ":" << mSec);
00166    return true;
00167 }
00168 
00169 /* ANSI-C code produced by gperf version 2.7.2 */
00170 /* Command-line: gperf -L ANSI-C -t -k '*' dayofweek.gperf  */
00174 struct days { char name[32]; DayOfWeek day; };
00175 
00176 #ifdef __GNUC__
00177 __inline
00178 #else
00179 #ifdef __cplusplus
00180 inline
00181 #endif
00182 #endif
00183 static unsigned int
00184 dayofweek_hash (register const char *str, register unsigned int len)
00185 {
00186   static unsigned char asso_values[] =
00187     {
00188       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00189       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00190       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00191       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00192       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00193       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00194       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00195        1, 13, 13, 13, 13, 13, 13,  5, 13, 13,
00196       13, 13, 13,  2,  0, 13, 13,  7, 13, 13,
00197       13, 13, 13, 13, 13, 13, 13,  7, 13, 13,
00198        0,  0, 13, 13,  4,  0, 13, 13, 13, 13,
00199        0,  0, 13, 13,  0, 13,  0,  0, 13, 13,
00200       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00201       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00202       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00203       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00204       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00205       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00206       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00207       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00208       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00209       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00210       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00211       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00212       13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00213       13, 13, 13, 13, 13, 13
00214     };
00215   register int hval = len;
00216 
00217   switch (hval)
00218     {
00219       default: /*FALLTHRU*/
00220       case 3:
00221         hval += asso_values[(unsigned char)str[2]];
00222         /*FALLTHRU*/
00223       case 2:
00224         hval += asso_values[(unsigned char)str[1]];
00225         /*FALLTHRU*/
00226       case 1:
00227         hval += asso_values[(unsigned char)str[0]];
00228         break;
00229     }
00230   return hval;
00231 }
00232 
00233 #ifdef __GNUC__
00234 __inline
00235 #endif
00236 struct days *
00237 in_dayofweek_word_set (register const char *str, register unsigned int len)
00238 {
00239    static const unsigned int MIN_WORD_LENGTH = 3;
00240    static const unsigned int MAX_WORD_LENGTH = 3;
00241    static const int MAX_HASH_VALUE = 12;
00242    
00243    static struct days wordlist[] =
00244     {
00245       {""}, {""}, {""},
00246       {"Tue", Tue},
00247       {"Fri", Fri},
00248       {"Sun", Sun},
00249       {""},
00250       {"Thu", Thu},
00251       {"Mon", Mon},
00252       {""},
00253       {"Wed", Wed},
00254       {""},
00255       {"Sat", Sat}
00256     };
00257 
00258   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
00259     {
00260       register int key = dayofweek_hash (str, len);
00261 
00262       if (key <= MAX_HASH_VALUE && key >= 0)
00263         {
00264           register const char *s = wordlist[key].name;
00265 
00266           if (*str == *s && !strcmp (str + 1, s + 1))
00267             return &wordlist[key];
00268         }
00269     }
00270   return 0;
00271 }
00272 
00273 DayOfWeek
00274 DateCategory::DayOfWeekFromData(const Data& dow)
00275 {
00276    static const unsigned int MIN_WORD_LENGTH = 3;
00277    static const unsigned int MAX_WORD_LENGTH = 3;
00278    static const int MAX_HASH_VALUE = 12;
00279 
00280    register const char *str = dow.data();
00281    register Data::size_type len = dow.size();
00282 
00283    static struct days wordlist[] =
00284       {
00285          {""}, {""}, {""},
00286          {"Tue", Tue},
00287          {"Fri", Fri},
00288          {"Sun", Sun},
00289          {""},
00290          {"Thu", Thu},
00291          {"Mon", Mon},
00292          {""},
00293          {"Wed", Wed},
00294          {""},
00295          {"Sat", Sat}
00296       };
00297 
00298    if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
00299    {
00300       register int key = dayofweek_hash (str, (unsigned int)len);
00301       
00302       if (key <= MAX_HASH_VALUE && key >= 0)
00303       {
00304          register const char *s = wordlist[key].name;
00305          
00306          if (*str == *s && !strncmp (str+1, s+1, len-1))
00307          {
00308             return wordlist[key].day;
00309          }
00310       }
00311    }
00312    return Sun;
00313 }
00314 
00315 /* ANSI-C code produced by gperf version 2.7.2 */
00316 /* Command-line: gperf -L ANSI-C -t -k '*' month.gperf  */
00320 struct months { char name[32]; Month type; };
00321 
00322 /* maximum key range = 31, duplicates = 0 */
00323 
00324 #ifdef __GNUC__
00325 __inline
00326 #else
00327 #ifdef __cplusplus
00328 inline
00329 #endif
00330 #endif
00331 static unsigned int
00332 month_hash (register const char *str, register unsigned int len)
00333 {
00334    static unsigned char asso_values[] =
00335       {
00336          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00337          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00338          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00339          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00340          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00341          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00342          34, 34, 34, 34, 34, 15, 34, 34,  8, 34,
00343          5, 34, 34, 34,  0, 34, 34, 10,  3, 14,
00344          34, 34, 34,  9, 34, 34, 34, 34, 34, 34,
00345          34, 34, 34, 34, 34, 34, 34, 10,  0,  0,
00346          34,  0, 34, 10, 34, 34, 34, 34,  4, 34,
00347          0,  0,  0, 34,  0, 34,  0,  0,  0, 34,
00348          34, 10, 34, 34, 34, 34, 34, 34, 34, 34,
00349          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00350          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00351          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00352          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00353          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00354          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00355          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00356          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00357          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00358          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00359          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00360          34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
00361          34, 34, 34, 34, 34, 34
00362       };
00363    register int hval = len;
00364 
00365    switch (hval)
00366    {
00367       default: /*FALLTHRU*/
00368       case 3:
00369          hval += asso_values[(unsigned char)str[2]];
00370          /*FALLTHRU*/
00371       case 2:
00372          hval += asso_values[(unsigned char)str[1]];
00373          /*FALLTHRU*/
00374       case 1:
00375          hval += asso_values[(unsigned char)str[0]];
00376          break;
00377    }
00378    return hval;
00379 }
00380 
00381 Month
00382 DateCategory::MonthFromData(const Data& mon)
00383 {
00384    static const unsigned int MIN_WORD_LENGTH = 3;
00385    static const unsigned int MAX_WORD_LENGTH = 3;
00386    static const int MAX_HASH_VALUE = 33;
00387 
00388    register const char *str = mon.data();
00389    register Data::size_type len = mon.size();
00390 
00391    static struct months wordlist[] =
00392       {
00393          {""}, {""}, {""},
00394          {"Jun", Jun},
00395          {""}, {""},
00396          {"Nov", Nov},
00397          {"Jul", Jul},
00398          {"Feb", Feb},
00399          {""}, {""},
00400          {"Dec", Dec},
00401          {"Sep", Sep},
00402          {"Jan", Jan},
00403          {""}, {""}, {""},
00404          {"Oct", Oct},
00405          {"Apr", Apr},
00406          {""}, {""}, {""}, {""},
00407          {"Mar", Mar},
00408          {""}, {""}, {""}, {""},
00409          {"Aug", Aug},
00410          {""}, {""}, {""}, {""},
00411          {"May", May}
00412       };
00413 
00414    if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
00415    {
00416       register int key = month_hash (str, (unsigned int)len);
00417 
00418       if (key <= MAX_HASH_VALUE && key >= 0)
00419       {
00420          register const char *s = wordlist[key].name;
00421 
00422          if (*str == *s && !strncmp (str + 1, s + 1, mon.size()-1))
00423             return wordlist[key].type;
00424       }
00425    }
00426    return Jan;
00427 }
00428 
00429 const DayOfWeek& 
00430 DateCategory::dayOfWeek() const 
00431 {
00432    checkParsed();
00433    return mDayOfWeek;
00434 }
00435 
00436 int&
00437 DateCategory::dayOfMonth() 
00438 {
00439    checkParsed();
00440    return mDayOfMonth;
00441 }
00442 
00443 int 
00444 DateCategory::dayOfMonth() const 
00445 {
00446    checkParsed();
00447    return mDayOfMonth;
00448 }
00449 
00450 Month& 
00451 DateCategory::month() 
00452 {
00453    checkParsed();
00454    return mMonth;
00455 }
00456 
00457 Month
00458 DateCategory::month() const
00459 {
00460    checkParsed();
00461    return mMonth;
00462 }
00463 
00464 int& 
00465 DateCategory::year() 
00466 {
00467    checkParsed();
00468    return mYear;
00469 }
00470 
00471 int
00472 DateCategory::year() const 
00473 {
00474    checkParsed();
00475    return mYear;
00476 }
00477 
00478 int&
00479 DateCategory::hour() 
00480 {
00481    checkParsed();
00482    return mHour;
00483 }
00484 
00485 int
00486 DateCategory::hour() const 
00487 {
00488    checkParsed();
00489    return mHour;
00490 }
00491 
00492 int&
00493 DateCategory::minute() 
00494 {
00495    checkParsed();
00496    return mMin;
00497 }
00498 
00499 int
00500 DateCategory::minute() const 
00501 {
00502    checkParsed();
00503    return mMin;
00504 }
00505 
00506 int&
00507 DateCategory::second() 
00508 {
00509    checkParsed();
00510    return mSec;
00511 }
00512 
00513 int
00514 DateCategory::second() const 
00515 {
00516    checkParsed();
00517    return mSec;
00518 }
00519 
00520 void
00521 DateCategory::parse(ParseBuffer& pb)
00522 {
00523    // Mon, 04 Nov 2002 17:34:15 GMT
00524 
00525    const char* anchor = pb.skipWhitespace();
00526 
00527    pb.skipToChar(Symbols::COMMA[0]);
00528    Data dayOfWeek;
00529    pb.data(dayOfWeek, anchor);
00530    mDayOfWeek = DateCategory::DayOfWeekFromData(dayOfWeek);
00531 
00532    pb.skipChar(Symbols::COMMA[0]);
00533 
00534    pb.skipWhitespace();
00535 
00536    mDayOfMonth = pb.integer();
00537 
00538    anchor = pb.skipWhitespace();
00539    pb.skipNonWhitespace();
00540 
00541    Data month;
00542    pb.data(month, anchor);
00543    mMonth = DateCategory::MonthFromData(month);
00544 
00545    pb.skipWhitespace();
00546    mYear = pb.integer();
00547 
00548    pb.skipWhitespace();
00549 
00550    mHour = pb.integer();
00551    pb.skipChar(Symbols::COLON[0]);
00552    mMin = pb.integer();
00553    pb.skipChar(Symbols::COLON[0]);
00554    mSec = pb.integer();
00555 
00556    pb.skipWhitespace();
00557    pb.skipChar('G');
00558    pb.skipChar('M');
00559    pb.skipChar('T');
00560 
00561    pb.skipWhitespace();
00562    pb.assertEof();
00563 }
00564 
00565 ParserCategory* 
00566 DateCategory::clone() const
00567 {
00568    return new DateCategory(*this);
00569 }
00570 
00571 ParserCategory* 
00572 DateCategory::clone(void* location) const
00573 {
00574    return new (location) DateCategory(*this);
00575 }
00576 
00577 ParserCategory* 
00578 DateCategory::clone(PoolBase* pool) const
00579 {
00580    return new (pool) DateCategory(*this, pool);
00581 }
00582 
00583 static void pad2(const int x, EncodeStream& str)
00584 {
00585    if (x < 10)
00586    {
00587       str << Symbols::ZERO[0];
00588    }
00589    str << x;
00590 }
00591 
00592 EncodeStream& 
00593 DateCategory::encodeParsed(EncodeStream& str) const
00594 {
00595    str << DayOfWeekData[mDayOfWeek] // Mon
00596        << Symbols::COMMA[0] << Symbols::SPACE[0];
00597    
00598    pad2(mDayOfMonth, str);  //  04
00599 
00600    str << Symbols::SPACE[0]
00601        << MonthData[mMonth] << Symbols::SPACE[0] // Nov
00602        << mYear << Symbols::SPACE[0]; // 2002
00603 
00604    pad2(mHour, str);
00605    str << Symbols::COLON[0];
00606    pad2(mMin, str);
00607    str << Symbols::COLON[0];
00608    pad2(mSec, str);
00609    str << " GMT";
00610 
00611    return str;
00612 }
00613 
00614 
00615 /* ====================================================================
00616  * The Vovida Software License, Version 1.0 
00617  * 
00618  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00619  * 
00620  * Redistribution and use in source and binary forms, with or without
00621  * modification, are permitted provided that the following conditions
00622  * are met:
00623  * 
00624  * 1. Redistributions of source code must retain the above copyright
00625  *    notice, this list of conditions and the following disclaimer.
00626  * 
00627  * 2. Redistributions in binary form must reproduce the above copyright
00628  *    notice, this list of conditions and the following disclaimer in
00629  *    the documentation and/or other materials provided with the
00630  *    distribution.
00631  * 
00632  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00633  *    and "Vovida Open Communication Application Library (VOCAL)" must
00634  *    not be used to endorse or promote products derived from this
00635  *    software without prior written permission. For written
00636  *    permission, please contact vocal@vovida.org.
00637  *
00638  * 4. Products derived from this software may not be called "VOCAL", nor
00639  *    may "VOCAL" appear in their name, without prior written
00640  *    permission of Vovida Networks, Inc.
00641  * 
00642  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00643  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00644  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00645  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00646  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00647  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00648  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00649  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00650  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00651  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00652  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00653  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00654  * DAMAGE.
00655  * 
00656  * ====================================================================
00657  * 
00658  * This software consists of voluntary contributions made by Vovida
00659  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00660  * Inc.  For more information on Vovida Networks, Inc., please see
00661  * <http://www.vovida.org/>.
00662  *
00663  */