[папа STL] Alexander Stepanov "Notes on Programming"
От: Вертер  
Дата: 06.02.07 00:03
Оценка: 104 (14)
Alexander Stepanov опубликовал лекции "Notes on Programming".

Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.
Re: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 07:45
Оценка: +6
Здравствуйте, Вертер, Вы писали:

В>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


В каждой програмистской конторе написать большими буквами и прибить к стене.

One could write beautiful code even in assembly. And if I could, I must.


Specifically I decided to use the following principles:

1. the code should be partitioned into functions;
2. every function should be most 20 lines of code;
3. functions should not depend on the global state but only on the arguments;
4. every function is either general or application specific, where general function is useful to other applications;
5. every function that could be made general – should be made general;
6. the interface to every function should be documented;
7. the global state should be documented by describing both semantics of individual variables and the global invariants.

The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.

В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 08:01
Оценка: +1 :)
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Вертер, Вы писали:


В>>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


Ш>В каждой програмистской конторе написать большими буквами и прибить к стене.


Ш>

Ш>One could write beautiful code even in assembly. And if I could, I must.


Ну да...
Только производительность 30 строк ассемблерного кода в день
это не то же самое, что и 30 строк кода на C++
Т.е. в строчках получается одинаково, но строчки "весят" по-разному.

Ш>

Ш>Specifically I decided to use the following principles:

Ш>1. the code should be partitioned into functions;
Ш>2. every function should be most 20 lines of code;
Ш>3. functions should not depend on the global state but only on the arguments;
Ш>4. every function is either general or application specific, where general function is useful to other applications;
Ш>5. every function that could be made general – should be made general;
Ш>6. the interface to every function should be documented;
Ш>7. the global state should be documented by describing both semantics of individual variables and the global invariants.

Ш>The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.


Тут прибивать на стену нечего.
Это почти в каждой нормальной фирме оформлено как "coding standards"
с кучей checklists.
Все эти простые правила практически всем известны.
Но они работают только тогда, когда их последовательно и везде применяют.
Т.е. проблема не в правилах, а в дисциплине их применения.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 09:53
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Шахтер, Вы писали:


Ш>>Здравствуйте, Вертер, Вы писали:


В>>>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>>>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


Ш>>

Ш>>One could write beautiful code even in assembly. And if I could, I must.


А>Ну да...

А>Только производительность 30 строк ассемблерного кода в день
А>это не то же самое, что и 30 строк кода на C++
А>Т.е. в строчках получается одинаково, но строчки "весят" по-разному.

А это тут причем?

Ш>>

Ш>>Specifically I decided to use the following principles:

Ш>>1. the code should be partitioned into functions;
Ш>>2. every function should be most 20 lines of code;
Ш>>3. functions should not depend on the global state but only on the arguments;
Ш>>4. every function is either general or application specific, where general function is useful to other applications;
Ш>>5. every function that could be made general – should be made general;
Ш>>6. the interface to every function should be documented;
Ш>>7. the global state should be documented by describing both semantics of individual variables and the global invariants.

Ш>>The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.


А>Тут прибивать на стену нечего.

А>Это почти в каждой нормальной фирме оформлено как "coding standards"

Coding standards -- это нечто иное.

А>с кучей checklists.

А>Все эти простые правила практически всем известны.

Почти никому не известны. Достаточно код почитать, который эти "все" пишут.

А>Но они работают только тогда, когда их последовательно и везде применяют.

А>Т.е. проблема не в правилах, а в дисциплине их применения.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 10:00
Оценка: +2 :)
А>Тут прибивать на стену нечего.
А>Это почти в каждой нормальной фирме оформлено как "coding standards"
А>с кучей checklists.
А>Все эти простые правила практически всем известны.
А>Но они работают только тогда, когда их последовательно и везде применяют.
А>Т.е. проблема не в правилах, а в дисциплине их применения.

И тем не менее, постоянно плодятся горы говно-кода. Знаю о некоем проекте. Кошмар страшенный, кода — уже за миллион(ы?) строк перевалило. Считают себя немерянными профессионалами, на уровне незыблемых истин — запрет использования СТЛ (дада, они до сих пор уверены, что компиляторы С++ — плохие и с шаблонами все плохо), У них тоже много жестких правил, которым они неукоснительно следуют. Но толку увы, нет. Навороты в дизайне такие, что мифические индусы, которых так любят обсуждать, плачут от зависти. Все течет, падает, жрет память гигами, работает медленно, как будто на жаве или питоне писали. Отчаявшись что-то улучшить, постоянно придумывают новые правила. Недавно решили использовать ворнинг -Weff++ или что там, так теперь заняты тем, что забивают тысячи строк ворнингов фиктивными определениями конструкторов копирования и операторов присваивания, после вызова которых все все равно радостно падает. Они — дисциплинированы, но увы, толку нет.
Потому как одно дело то, что человек считает своими принципами и другое, что ему навязывают.
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Lorenzo_LAMAS  
Дата: 06.02.07 10:12
Оценка: 6 (1) +2 :)))
Здравствуйте, Шахтер, Вы писали:

Ш>В каждой програмистской конторе написать большими буквами и прибить к стене.


Это в башку надо вбивать, а не на стены
Of course, the code must be complete enough to compile and link.
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 10:20
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, Шахтер, Вы писали:


Ш>>>Здравствуйте, Вертер, Вы писали:


В>>>>Alexander Stepanov опубликовал лекции "Notes on Programming".


В>>>>Alexander Stepanov: I have been programming for over 30 years. I wrote my first program in 1969 and became a full time programmer in 1972.


Ш>>>В каждой програмистской конторе написать большими буквами и прибить к стене.


Ш>>>

Ш>>>One could write beautiful code even in assembly. And if I could, I must.


А>>Ну да...

А>>Только производительность 30 строк ассемблерного кода в день
А>>это не то же самое, что и 30 строк кода на C++
А>>Т.е. в строчках получается одинаково, но строчки "весят" по-разному.

Ш>А это тут причем?

Да в общем ни причем. Так, реплика в тему (или не в тему )...

Ш>>>

Ш>>>Specifically I decided to use the following principles:

Ш>>>1. the code should be partitioned into functions;
Ш>>>2. every function should be most 20 lines of code;
Ш>>>3. functions should not depend on the global state but only on the arguments;
Ш>>>4. every function is either general or application specific, where general function is useful to other applications;
Ш>>>5. every function that could be made general – should be made general;
Ш>>>6. the interface to every function should be documented;
Ш>>>7. the global state should be documented by describing both semantics of individual variables and the global invariants.

Ш>>>The result of my experiment was quite astonishing. The code did not contain serious bugs. There were typos: I had to change AND to OR, etc. But I did not need patches. And over 95% of the code was in general functions! I felt quite proud.


А>>Тут прибивать на стену нечего.

А>>Это почти в каждой нормальной фирме оформлено как "coding standards"

Ш>Coding standards -- это нечто иное.

А что это? Те же самые рекомендации по форматированию и структурированию кода.
В нашем есть практически все, о чем пишет Stepanov.
Ну разве только "the code should be partitioned into functions" в явном виде отсутстует,
ввиду очевидности правила.

А>>с кучей checklists.

А>>Все эти простые правила практически всем известны.

Ш>Почти никому не известны. Достаточно код почитать, который эти "все" пишут.


Ну про "every function should be most 20 lines of code" я уже знал на 1-м курсе.
Твоя фраза только поддверждает мое наблюдение,
что проблема не в том, что народ не знает об этих простых правилах,
а в том, что правила не применяются .
Кстати, я почти уверен, что если тебя кто-то постоянно будет долбить,
по всем этим пунктам, то ты его довольно быстро начнешь посылать куда подальше.
Или ты прямо сейчас перестанешь писать функции длиннее 20 строк?

Но в принципе польза от правил от Степанова есть.
Одно дело когда их озвучит уважаемый в программистком мире человек.
И совсем другое дело, когда о них раскажет препод на скучней лекции по технологии программирования
или кто-то напишет это в мало кем читаемом coding standards/guidelines
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 10:26
Оценка: :))
Здравствуйте, Аноним, Вы писали:

А>>Тут прибивать на стену нечего.

А>>Это почти в каждой нормальной фирме оформлено как "coding standards"
А>>с кучей checklists.
А>>Все эти простые правила практически всем известны.
А>>Но они работают только тогда, когда их последовательно и везде применяют.
А>>Т.е. проблема не в правилах, а в дисциплине их применения.

А>И тем не менее, постоянно плодятся горы говно-кода.


Ну дак это вечная проблема, причем не только в программировании
Вроде в теории все должно быть хорошо, а вот людишки не те...
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Анатолий Широков СССР  
Дата: 06.02.07 14:00
Оценка: +1
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Шахтер, Вы писали:


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>Это в башку надо вбивать, а не на стены


А если не вбивается, то сносить такую башку напрочь.
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Аноним  
Дата: 06.02.07 14:02
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>>Здравствуйте, Шахтер, Вы писали:


Ш>>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>>Это в башку надо вбивать, а не на стены


АШ>А если не вбивается, то сносить такую башку напрочь.


Да господа....
Вам в Армию надо программировать.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 06.02.07 14:22
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Шахтер, Вы писали:


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>Это в башку надо вбивать, а не на стены


Удивляюсь я вам всем: вбивать, учить...

Обучение получается гораздо проще по-другому: есть требования к проекту, есть сроки.
Не готово, не работает — лишение премии. Регулярный срыв — увольнение.

С такими требованиями люди сами научатся оптимизировать свою работу, выбирать правильные coding styles. Иначе — зачем такие программисты.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 14:56
Оценка: :))
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Шахтер, Вы писали:


Ш>>В каждой програмистской конторе написать большими буквами и прибить к стене.


L_L>Это в башку надо вбивать, а не на стены


Знаешь как в Самсунге учат английскому?
В туалете выше писуаров на уровне глаз вешают листочки с английскими словами. Листочки регулярно меняют.
Видимо, помогает.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Анатолий Широков СССР  
Дата: 06.02.07 15:20
Оценка: +1
АШ>>А если не вбивается, то сносить такую башку напрочь.

А>Да господа....

А>Вам в Армию надо программировать.

Нет, просто наболело.
Re[2]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 15:22
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

[]

+1

Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Шахтер Интернет  
Дата: 06.02.07 15:46
Оценка: +1 :)
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, Шахтер, Вы писали:


КЛ>[]


КЛ>+1


КЛ>Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.


Разумеется, следование данному правилу (как и остальным) нельзя доводить до абсурда.
Но писать вот такие функции...


unsigned short
IsakmpSaCls::ProcessMainMode(isakmp_hdr *hdr, IsakmpSaCls **delSa,
                             ERROR_CODE &error)
{
  sa_payload *sap;
  proposal_payload *prop;
  isakmp_hdr *newhdr;
  key_x_payload *keyp;
  nonce_payload *nonceI, *nonceR;
  id_payload *idp;
  hash_payload *hashp;
  cert_payload *cert;
  notify_payload *notify;
  vendor_id_payload *vend, *vend1 = 0; // Q00959911 introduces vend1
  IsakmpSaCls *testSa;
  IsakmpCallBackStr *cb;
  UINT8 *idData = 0;
  UINT8 *certData, *sigData;
  unsigned int idLen = 0;
  unsigned int sizeofCertPayload = 5;
  unsigned int ourKeySize;
  unsigned int badKeySize = IKEDHCls::PublicValueLength(saDHGroup, BAD_AES); // too early for aesCompatOn (sometimes)
  UINT16 hashlen, certLen;
  UINT16 isaError = AUTH_FAILED;
  ERROR_CODE localError = SUCCESS;
  UINT8 uidType, initiatorIdType = 0;

  if (aesCompatOn == BAD_AES)
  {
      ourKeySize = IKEDHCls::PublicValueLength(saDHGroup, BAD_AES);
  }
  else
  {
      ourKeySize = IKEDHCls::PublicValueLength(saDHGroup);
  }

  // The following is an adjustment made to cope with "version 3" (2.0)
  // clients and servers, which used sizeof(cert_payload) throughout the
  // code and thus placed the start of the certificate data one byte later
  // than it should be...
  if ((saCESVersion == 3) || (saNewOakVersion == 3))
    sizeofCertPayload = 6;
  switch (saState)
  {
    case OAK_MM_SA_SETUP:
      // Make sure we actually got back an SA payload...
      sap = (sa_payload *)IsakmpFindPayload(hdr, ISA_SA);
      if (!sap)
        return 0xFFFF;
      // Find out what was accepted.
      prop = (proposal_payload *)((UINT8 *)sap + sizeof(sa_payload));
      if ((prop->prop_num != 1) || (prop->protocol_id != PROTO_ISAKMP) ||
          (prop->num_transforms != 1))
        {
          if ( isakmpVerbose )
            isakmpEventLog->Event(EventLog::DEBUG,
                                  "Proposal bad syntax: prop_num:%x protocol_id:%x transforms:%x",
                                  prop->prop_num, prop->protocol_id, prop->num_transforms);
          return PROPOSAL_BAD_SYNTAX;
        }

      // Check for the hash algorithm attribute.
      saHashAlg = GetBasicAttributeValue(prop, OAK_HASH_ALG);

      // CR147031: FIPS only allows SHA hashing, so enforce it here. Note: we only proposed SHA.
      if (  FIPSCls::Enabled() && ( saHashAlg == HASH_MD5 ) )
        {
          isakmpEventLog->Event(EventLog::DEBUG,
                                "Proposal rejected: FIPS requires SHA hashing algorithm. ");
        }

      if ((saHashAlg != HASH_MD5) && (saHashAlg != HASH_SHA))
        {
          if ( isakmpVerbose )
            isakmpEventLog->Event(EventLog::DEBUG,
                                  "Proposal bad syntax: hash Algorithm:%x", saHashAlg);
          return PROPOSAL_BAD_SYNTAX;
        }

      // Cool - we have an accepted proposal.  Set the responder's cookie
      // and lose the timer.
      SetResponderCookie((UINT32 *)hdr->resp_cookie);
      CancelTimer();
      // Check for a CES (server) version number.
      vend = (vendor_id_payload *)IsakmpFindPayload(hdr, ISA_VEND_ID);
      while (vend)
        {
          UINT32 *vendDataPtr = (UINT32 *)((UINT8 *)vend +
                                           sizeof(vendor_id_payload));
          if ((ntohs(vend->payload_len) == sizeof(vendor_id_payload) + 8) &&
#ifdef LITTLE_ENDIAN
              (*vendDataPtr == 0x53454E42)    // BNES
#else
              (*vendDataPtr == 0x424E4553)    // BNES
#endif
              )
            {
              saCESVersion = ntohl(*(vendDataPtr + 1));

              // CD_AES : obviously, we are a compatible version ; hence self test skipped; only peer is checked
#ifdef _DEBUG
              isakmpEventLog->Event(EventLog::MEDIUM, "mainmode saCESVersion = 0x%x", saCESVersion);
#endif
              if (saCESVersion < AES_COMPAT_VERSION)
              {
                  aesCompatOn = BAD_AES; // we are talking to old code
                  //updating ourKeySize to incorrect value for kluge to work
                  ourKeySize = badKeySize;
                  if (isakmpVerbose) printf("ProcessMainMode: updated aesCompatOn to 0x%x in this %x ourkeysz to %x saState %d\n", aesCompatOn, (UINT32)this, ourKeySize, saState);
              }
              if (saCESVersion < MTU_COMPAT_VERSION)
              {
                  this->mtuCompatState = MTU_NOT_OKAY;
              }
              else
              {
                  this->mtuCompatState = MTU_OKAY;
              }
              if (saCESVersion == 3)
                sizeofCertPayload = 6;
            }
          else if ((ntohs(vend->payload_len) == sizeof(vendor_id_payload) + 16))
            {
#ifdef LITTLE_ENDIAN
              if (*vendDataPtr == 0x13D7CAAF  &&        // DPD Vendor-id
                  (*(vendDataPtr+1) == 0xC9F1A168 ) &&
                  (*(vendDataPtr+2) == 0xFC96866B ) &&
                  (*(vendDataPtr+3) == 0x00015777 ))    // Major=01 Minor=00
#else
                if (*vendDataPtr == 0xAFCAD713 &&
                    (*(vendDataPtr+1) == 0x68A1F1C9 ) &&
                    (*(vendDataPtr+2) == 0x6B8696FC ) &&
                    (*(vendDataPtr+3) == 0x77570100 ))
#endif
                  {
                    saDPDVendIdReceived = TRUE; // Q00959911
                    //Q00553988 Phanton tunnels on Branch Office, to multiple different vendor platforms
                    if(saSession && saSession->GetAccount()->IsVendorIdEnabled())
                      if (saSession && saSession->GetAccount()->GetAllowDeadPeerDetection() )
                        saDPDExchange = TRUE;
                  }
            }

          vend = (vendor_id_payload *)IsakmpFindPayload((generic_payload*)vend, ISA_VEND_ID);
        }

      // We need to set up a new packet buffer, and start the Diffie-Hellman
      // process now.
      delete [] saMessage;
      saDH = new DHCls(saDHGroup, aesCompatOn);
      myDHPublic = new UINT8[ourKeySize];
      saMessageLength = sizeof(isakmp_hdr) + sizeof(key_x_payload)
                        + ourKeySize + sizeof(nonce_payload) + 20;
      if (saAuthMethod == RSA_SIG)
        {
          saMessageLength += sizeofCertPayload;
          if (saSession)
            {
              //DnCls *issueDn = GetValidIssuer (saSession, &localError);
              if (localError == SUCCESS)
                {
                  const char *issuer = GetIssuerName(saSession, &localError);
                  if (issuer)
                    {
                      int ca_len = strlen (issuer);
                      saMessageLength += ca_len;
                    }
                }
            }
        }
      
      saMessage = new UINT8[saMessageLength];
      if (!saDH || !myDHPublic || !saMessage)
      {
        // We lose big time!
        delete this;
        return 0xFFFF;
      }
      // Set up the ISAKMP header...
      GetCookies((UINT32 *)saMessage);
      newhdr = (isakmp_hdr *)saMessage;
#ifdef LITTLE_ENDIAN
      *((UINT32 *)saMessage+4) = 0x00021004;
#else
      *((UINT32 *)saMessage+4) = 0x04100200;
#endif

      newhdr->mess_id = 0;
      newhdr->len = htonl(saMessageLength);
      // ...and the key exchange payload...
      // We need to save our public value internally.
      keyp = (key_x_payload *)(saMessage + sizeof(isakmp_hdr));

      keyp->next_payload = ISA_NONCE;
      keyp->reserved = 0;
      keyp->payload_len = htons(sizeof(key_x_payload) + saDH->PublicValueLength());
#ifdef LOAD_TEST
      // NOTE: We request a semaphore here, because the current Diffie-Hellman
      // code is single-threaded.  This doesn't impact the server, where only
      // tIsakmp does D-H, but it does impact the load generator.
      semTake(ipsecTunnelTableSem, WAIT_FOREVER);
#endif
      if (FALSE == saDH->Setup(*isakmpRng, myDHPublic))
        {
          isakmpEventLog->Event(EventLog::HIGH,
                          "Error in Diffie-Hellman Setup, group=%u", (UINT32)saDHGroup);
          delete this;
          return 0xFFFF;
        }

#ifdef LOAD_TEST
      semGive(ipsecTunnelTableSem);
#endif

      bcopy((char *)myDHPublic, (char *)keyp + sizeof(key_x_payload),
            saDH->PublicValueLength());
      // ...and the nonce.
      // We need the nonce to generate SKEYID later, but we'll just save
      // it here in the message itself.
      nonceI = (nonce_payload *)((UINT8 *)keyp + sizeof(key_x_payload)
                                 + saDH->PublicValueLength());
      *((UINT16 *)nonceI) = 0;
      nonceI->payload_len = htons(sizeof(nonce_payload) + 20);
      isakmpRng->GetBlock((UINT8 *)nonceI + sizeof(nonce_payload), 20);

      if (saAuthMethod == RSA_SIG)
      {
        nonceI->next_payload = ISA_CERT_REQ;
        cert = (cert_payload *)((UINT8 *)nonceI + sizeof(nonce_payload) + 20);
        *((UINT16 *)cert) = 0;
        cert->payload_len = htons(sizeofCertPayload);
        cert->cert_spec = 4;

        if (saSession)
          {
            if (localError == SUCCESS)
              {
                const char *issuer = GetIssuerName(saSession, &localError);

                if (issuer)
                  {
                    char *p = (char *)cert;
                    int ca_len = strlen (issuer);
                    p += 5;
                    strcpy (p, issuer);
                    cert->payload_len = htons (sizeofCertPayload + ca_len);
                  }    
              }
          }
      }

      // All done... Reset our state and the retransmit timer.
      saState = OAK_MM_KEY_EXCH;
      SetTimer(TIMER_RETRY, saIsakmpTimeout);
      break;

    case OAK_MM_KEY_EXCH:

      // Need to have key exchange and nonce payloads.
      keyp = (key_x_payload *)IsakmpFindPayload(hdr, ISA_KE);
      if (!keyp)
        return 0xFFFF;
      nonceI = (nonce_payload *)IsakmpFindPayload(hdr, ISA_NONCE);
      if (!nonceI)
        return 0xFFFF;

      // Q00959911 - Begin
      // If receiving the DPD Vendor Id has been delayed up until this
      // point, process it now - the following code is replicated from
      // case OAK_MM_SA_SETUP
      if (!saDPDVendIdReceived)
        {
          vend1 = (vendor_id_payload *)IsakmpFindPayload(hdr, ISA_VEND_ID);
          while (vend1)
            {
              UINT32 *vendDataPtr = (UINT32 *)((UINT8 *)vend1 +
                                               sizeof(vendor_id_payload));
              if ((ntohs(vend1->payload_len) == sizeof(vendor_id_payload) + 8) &&
#ifdef LITTLE_ENDIAN
                  (*vendDataPtr == 0x53454E42)    // BNES
#else
                  (*vendDataPtr == 0x424E4553)    // BNES
#endif
                  )
                {
                  saCESVersion = ntohl(*(vendDataPtr + 1));

                  // CD_AES : obviously, we are a compatible version ; hence self test skipped; only peer is checked
#ifdef _DEBUG
                  isakmpEventLog->Event(EventLog::MEDIUM, "mainmode saCESVersion = 0x%x", saCESVersion);
#endif
                  if (saCESVersion < AES_COMPAT_VERSION)
                    {
                      aesCompatOn = BAD_AES; // we are talking to old code
                      //updating ourKeySize to incorrect value for kluge to work
                      ourKeySize = badKeySize;
                      if (isakmpVerbose) printf("ProcessMainMode: updated aesCompatOn to 0x%x in this %x ourkeysz to %x saState %d\n", aesCompatOn, (UINT32)this, ourKeySize, saState);
                    }
                  if (saCESVersion < MTU_COMPAT_VERSION)
                    {
                      this->mtuCompatState = MTU_NOT_OKAY;
                    }
                  else
                    {
                      this->mtuCompatState = MTU_OKAY;
                    }
                  if (saCESVersion == 3)
                    sizeofCertPayload = 6;
                }
              else if ((ntohs(vend1->payload_len) == sizeof(vendor_id_payload) + 16))
                {
#ifdef LITTLE_ENDIAN
                  if (*vendDataPtr == 0x13D7CAAF  &&        // DPD Vendor-id
                      (*(vendDataPtr+1) == 0xC9F1A168 ) &&
                      (*(vendDataPtr+2) == 0xFC96866B ) &&
                      (*(vendDataPtr+3) == 0x00015777 ))    // Major=01 Minor=00
#else
                    if (*vendDataPtr == 0xAFCAD713 &&
                        (*(vendDataPtr+1) == 0x68A1F1C9 ) &&
                        (*(vendDataPtr+2) == 0x6B8696FC ) &&
                        (*(vendDataPtr+3) == 0x77570100 ))
#endif
                      {
                        saDPDVendIdReceived = TRUE;
                        //Q00553988 Phanton tunnels on Branch Office, to multiple different vendor platforms
                        if(saSession && saSession->GetAccount()->IsVendorIdEnabled())
                          if (saSession && saSession->GetAccount()->GetAllowDeadPeerDetection() )
                            {
                              saDPDExchange = TRUE;
                            }
                      }
                }
              vend1 = (vendor_id_payload *)IsakmpFindPayload((generic_payload*)vend1, ISA_VEND_ID);
            }
        }
      // Q00959911 - End


      // We have the right payloads - cancel the retransmit timer.
      CancelTimer();
      // Is key exchange size wrong?
      // CD_AES ALERT !! test both sizes
      if ( ((ntohs(keyp->payload_len) - sizeof(key_x_payload)) != ourKeySize) &&
          ((ntohs(keyp->payload_len) - sizeof(key_x_payload)) != badKeySize) )
        return INVALID_KEY_INFO;

      // If signature mode, check for a cert request and ensure it
      // specifies the right cert type.
      if (saAuthMethod == RSA_SIG)
      {
        cert = (cert_payload *)IsakmpFindPayload(hdr, ISA_CERT_REQ);
        if (cert && (cert->cert_spec != 4))
          return BAD_CERT_REQ_SYNTAX;
      }

      // CD_AES : alert : we _should_ have parsed the VID by now...
      theirDHPublic = new UINT8[ourKeySize];
      if (!theirDHPublic)
      {
        delete this;
        return 0xFFFF;
      }

      bcopy((char *)keyp + sizeof(key_x_payload), (char *)theirDHPublic,
            ourKeySize);
      // If we are the responder, calculate our Diffie-Hellman values
      // and build our response message now.
      if (saIsakmpRole == RESPONDER)
      {
        if (ntohs(nonceI->payload_len) <= sizeof(nonce_payload))
          return PAYLOAD_MALFORMED;
        delete [] saMessage;
        saDH = new DHCls(saDHGroup, aesCompatOn);
        myDHPublic = new UINT8[ourKeySize];
        saMessageLength = sizeof(isakmp_hdr) + sizeof(key_x_payload)
                          + ourKeySize + sizeof(nonce_payload) + 20;
        if (saAuthMethod == RSA_SIG)
          saMessageLength += sizeofCertPayload;

        // Q00959911 - Begin
        // If we are doing DPD Exchange and DPD Vendor Id has not been
        // sent yet, we shall send it now
        // First we add to the message length
        if ( (!saDPDVendIdSent) && (saDPDExchange) )
          {
            saMessageLength += sizeof(vendor_id_payload) + 16;
          }
        // Q00959911 - End

        saMessage = new UINT8[saMessageLength];
        if (!saDH || !myDHPublic || !saMessage)
        {
          // We lose big time!
          delete this;
          return 0xFFFF;
        }

        // Set up the ISAKMP header...
        GetCookies((UINT32 *)saMessage);
        newhdr = (isakmp_hdr *)saMessage;
#ifdef LITTLE_ENDIAN
        *((UINT32 *)saMessage+4) = 0x00021004;
#else
        *((UINT32 *)saMessage+4) = 0x04100200;
#endif
        newhdr->mess_id = 0;
        newhdr->len = htonl(saMessageLength);
        // ...and the key exchange payload...
        // We need to save our public value internally.
        keyp = (key_x_payload *)(saMessage + sizeof(isakmp_hdr));
        keyp->next_payload = ISA_NONCE;
        keyp->reserved = 0;
        keyp->payload_len = htons(sizeof(key_x_payload)
                                  + saDH->PublicValueLength());
#ifdef LOAD_TEST
        semTake(ipsecTunnelTableSem, WAIT_FOREVER);
#endif
        if (FALSE == saDH->Setup(*isakmpRng, myDHPublic))
        {
          isakmpEventLog->Event(EventLog::HIGH,
                          "Error in Diffie-Hellman Setup, group=%u", (UINT32)saDHGroup);
          delete this;
          return 0xFFFF;
        }
#ifdef LOAD_TEST
        semGive(ipsecTunnelTableSem);
#endif
        bcopy((char *)myDHPublic, (char *)keyp + sizeof(key_x_payload),
              saDH->PublicValueLength());

        // ...and the nonce.
        nonceR = (nonce_payload *)((UINT8 *)keyp + sizeof(key_x_payload)
                                   + saDH->PublicValueLength());
        *((UINT16 *)nonceR) = 0;
        nonceR->payload_len = htons(sizeof(nonce_payload) + 20);
        isakmpRng->GetBlock((UINT8 *)nonceR + sizeof(nonce_payload), 20);

        if (saAuthMethod == RSA_SIG)
        {
          nonceR->next_payload = ISA_CERT_REQ;
          cert = (cert_payload *)((UINT8 *)nonceR+sizeof(nonce_payload)+20);
          *((UINT16 *)cert) = 0;
          cert->payload_len = htons(sizeofCertPayload);
          cert->cert_spec = 4;

          // Q00959911 - Begin
          // Add the Vendor Id payload after the Cert payload
          if ( (!saDPDVendIdSent) && (saDPDExchange) )
            {
              cert->next_payload = ISA_VEND_ID;
              vend1 = (vendor_id_payload *)((UINT8 *)cert + sizeofCertPayload);
              *((UINT16 *)vend1) = 0;
              vend1->payload_len = htons(sizeof(vendor_id_payload) + 16);
            }
          // Q00959911 - End
        }
        // Q00959911 - Begin
        else
          {
            // Add the Vendor Id payload after the Nonce payload
            if ( (!saDPDVendIdSent) && (saDPDExchange) )
              {
                nonceR->next_payload = ISA_VEND_ID;
                vend1 = (vendor_id_payload *)((UINT8 *)nonceR+sizeof(nonce_payload)+20);
                *((UINT16 *)vend1) = 0;
                vend1->payload_len = htons(sizeof(vendor_id_payload) + 16);
              }
          }

        // Fill in the values for the Vendor Id payload
        if ( (!saDPDVendIdSent) && (saDPDExchange) )
          {
#ifdef LITTLE_ENDIAN
            *((UINT32 *)vend1 + 1) = 0x13D7CAAF;        // DPD Vendor-id
            *((UINT32 *)vend1 + 2) = 0xC9F1A168;
            *((UINT32 *)vend1 + 3) = 0xFC96866B;
            *((UINT32 *)vend1 + 4) = 0x00015777;        // Major=01 Minor=00
#else
            *((UINT32 *)vend1 + 1) = 0xAFCAD713;        // DPD Vendor-id
            *((UINT32 *)vend1 + 2) = 0x68A1F1C9;
            *((UINT32 *)vend1 + 3) = 0x6B8696FC;
            *((UINT32 *)vend1 + 4) = 0x77570100;        // Major=01 Minor=00
#endif
            saDPDVendIdSent = TRUE;
          }
        // Q00959911 - End

      }
      // Otherwise, if we're the initiator, figure out the pointer to
      // our nonce in the current (old) transmission packet.
      else
      {
        nonceR = nonceI;
        nonceI = (nonce_payload *)(saMessage + sizeof(isakmp_hdr)
                                   + sizeof(key_x_payload)
                                   + saDH->PublicValueLength());
        if (ntohs(nonceR->payload_len) <= sizeof(nonce_payload))
          return PAYLOAD_MALFORMED;
      }
      // Do all those key material calculations...
      if (GenerateIsakmpKeys(nonceI, nonceR) == FALSE)
      {
        delete this;
        return 0xFFFF;
      }
      hashlen = (UINT16)prf->DigestSize();
      // Construct initiator's message.
      if (saIsakmpRole == INITIATOR)
      {
        delete [] saMessage;
        saMessage = 0;
        if (saAuthMethod == PRESHRD)
        {
          idLen = 4;
          idData = 0;
        }
        else
        {
          AlternateNameCls *altName = NULL;
          DnCls *serverDn = NULL;

          initiatorIdType = GetServerIdentity(saSession, saCESVersion, &serverDn, &altName, &idData, &idLen, &localError);
          //
          // If a supported id type is returned then we have a valid
          // server identity and certificate.  The type returned will
          // indicate if the serverDn or altName arg is set with the
          // actual identity info.
          //
          switch (initiatorIdType)
          {
            case ID_DER_ASN1_DN:
            if (serverDn != NULL)
            {
               // We already filled out idData in GetServerIdentity
               //localError = GetAsnFromDn(serverDn, &idData, &idLen);
            }
            else
            {
              idData = NULL;
              idLen = 0;
              localError = NO_SUBJECT_NAME;
            }
            break;

            case ID_IPV4_ADDR:
            case ID_USER_FQDN:
            case ID_FQDN:
            idData = NULL;
            idLen = 0;
            localError = ALTNAME_MISSING;
            //
            // Use our subject alternate name if we have one
            //
            if (altName != NULL)
            {
              char *altNameStr = (char *) (altName->GetAltNameStr());
              if (altNameStr != NULL)
              {
                if (initiatorIdType == ID_IPV4_ADDR)
                {
                    IpAddrCls serverAddr;

                    if ((localError = serverAddr.SetAscii(altNameStr)) == SUCCESS)
                    {
                      // TODO - check that serverAddr == saLocalAddr here?
                      idLen = 4;
                      idData = (UINT8 *) malloc(idLen);
                      if (idData != NULL)
                      {
                        *((UINT32 *) idData) = serverAddr;
                      }
                      else
                      {
                        idLen = 0;
                        localError = NO_MEMORY;
                      }
                    }
                }
                else
                {
                    idLen = strlen(altNameStr);
                    idData = (UINT8 *) malloc(idLen);
                    if (idData != NULL)
                    {
                        bcopy(altNameStr, (char *) idData, idLen);
                        localError = SUCCESS;
                    }
                    else
                    {
                        idLen = 0;
                        localError = NO_MEMORY;
                    }
                }
              }
            }
            break;

            default:
                 // localError is set by GetServerIdentity()
            break;
          }
          delete serverDn;
          delete altName;
        }

        if (localError != SUCCESS)
        {
            isakmpEventLog->Event(EventLog::PERSIST_HIGH,
                                  "Could not obtain local identity to send to %.*s, reason: %s",
                                  (UINT32)(EVENTLOGMAXTXT - 60),
                                  (UINT32)saRemoteIdString,
                                  (UINT32)errorCode.GetString(localError));
            if (saNewOakVersion)
              error = localError;
            delete this;
            return INVALID_KEY_INFO;
        }
        // If we have no existing ISAKMP SAs with the other side, send
        // an INITIAL-CONTACT Notify payload along with the rest of our
        // message.  This will inform the other side that it may clear
        // out any old SA state it may have.  (Specifically, it gets
        // around the problem of our boxes enforcing a "login limit"
        // of one when the other side reboots...)  If testSa exists
        // after this loop, then we DON'T send INITIAL-CONTACT.
        testSa = isakmpTable[IsadbHashFunction((UINT32)saLocalAddr,
                                               (UINT32)saRemoteAddr)];
        for (; testSa; testSa = testSa->nextSa)
        {
          if ((testSa != this) &&
              (testSa->saLocalAddr == saLocalAddr) &&
              (testSa->saRemoteAddr == saRemoteAddr) &&
              saSession && testSa->saSession &&
              (testSa->saSession->GetAccount() == saSession->GetAccount()))
            break;
        }
        // At first, we'll build this message as if it we were using
        // pre-shared keys.  We'll transmogrify it into the digital signature
        // format, if need be, in a little bit.  This allows us to pre-build
        // the ID payload and the hash we will sign in place.
        saMessageLength = sizeof(isakmp_hdr) + sizeof(id_payload) + idLen
          + sizeof(hash_payload) + hashlen;
        if (!testSa)
          saMessageLength += sizeof(notify_payload) + 16;
        saMessage = new UINT8[saMessageLength + MAX_PAD_SIZE];
        if (!saMessage)
        {
          /* svora: delete allocated memory */
          if(idData)
            {
              free(idData);
              idData=NULL;
            }

          // We lose big time!
          return 0xFFFF;
        }
        // Set up the ISAKMP header...
        GetCookies((UINT32 *)saMessage);
        newhdr = (isakmp_hdr *)saMessage;
#ifdef LITTLE_ENDIAN
        *((UINT32 *)saMessage+4) = 0x01021005;
#else
        *((UINT32 *)saMessage+4) = 0x05100201;
#endif
        newhdr->mess_id = 0;
        newhdr->len = htonl(saMessageLength);
        idp = (id_payload *)(saMessage + sizeof(isakmp_hdr));
        idp->reserved = 0;
        idp->payload_len = htons(sizeof(id_payload) + idLen);
        idp->protocol_id = 0;
        idp->port = 0;
        if (idData)
        {
          idp->id_type = initiatorIdType;
          bcopy((char *)idData, (char *)idp + sizeof(id_payload), idLen);
          free(idData);
          idData = NULL;
        }
        else
        {
          idp->id_type = ID_IPV4_ADDR;
          *((UINT32 *)idp + 2) = saLocalAddr;
        }
        idp->next_payload = ISA_HASH;
        hashp = (hash_payload *)((UINT8 *)idp + ntohs(idp->payload_len));
        *((UINT16 *)hashp) = 0;
        hashp->payload_len = htons(sizeof(hash_payload) + hashlen);
        prf->Update(myDHPublic, IKEDHCls::PublicValueLength(saDHGroup, aesCompatOn));
        prf->Update(theirDHPublic, IKEDHCls::PublicValueLength(saDHGroup, aesCompatOn));
        prf->Update((UINT8 *)saCookie, 16);
        prf->Update(initSaPayload, initSaPayloadLength);
        prf->Update((UINT8 *)idp + sizeof(generic_payload),
                    ntohs(idp->payload_len) - sizeof(generic_payload));
        prf->Final((UINT8 *)hashp + sizeof(hash_payload));
        if (saAuthMethod == RSA_SIG)
        {
          // Sign the data.
          if (!saSession || saSession->SignData(SEC_AUTHMETHOD_CERTIFICATE_RSA,
                                  (UINT8 *)hashp + sizeof(hash_payload),
                                  &sigData, &hashlen, &certData, &certLen,
                                  &localError) == FALSE)
          {
            if (saNewOakVersion)
              error = localError;
            delete this;
            return INVALID_KEY_INFO;
          }
          // Allocate a new message buffer, and rebuild...
          saMessageLength -= sizeof(hash_payload) + prf->DigestSize();
          saPreMessageLength = saMessageLength + sizeofCertPayload + certLen
            + sizeof(sig_payload) + hashlen;
          // If we're adding an INITIAL-CONTACT Notify, *don't* copy over
          // its length to the new message, since we haven't put it in yet!
          if (!testSa)
            saMessageLength -= sizeof(notify_payload) + 16;
          saPreMessage = new UINT8[saPreMessageLength + MAX_PAD_SIZE];
          if (!saPreMessage)
          {
            // We lose big time!
            return 0xFFFF;
          }
          newhdr->len = htonl(saPreMessageLength);
          idp->next_payload = ISA_CERT;
          bcopy((char *)saMessage, (char *)saPreMessage, saMessageLength);
          delete [] saMessage;
          saMessage = saPreMessage;
          cert = (cert_payload *)(saMessage + saMessageLength);
          saMessageLength = saPreMessageLength;
          saPreMessage = 0;
          saPreMessageLength = 0;
          cert->next_payload = ISA_SIG;
          cert->reserved = 0;
          cert->payload_len = htons(certLen + sizeofCertPayload);
          // Cert type is X.509 Certificate - Signature.
          cert->cert_spec = 4;
          bcopy((char *)certData, (char *)cert + sizeofCertPayload,
                certLen);
          hashp = (hash_payload *)((UINT8 *)cert + ntohs(cert->payload_len));
          *((UINT16 *)hashp) = 0;
          hashp->payload_len = htons(sizeof(sig_payload) + hashlen);
          bcopy((char *)sigData, (char *)hashp + sizeof(sig_payload),
                hashlen);
        }
        if (!testSa)
        {
          hashp->next_payload = ISA_NOTIFY;
          notify = (notify_payload *)
                   ((UINT8 *)hashp + ntohs(hashp->payload_len));
          *((UINT16 *)notify) = 0;
          notify->payload_len = htons(sizeof(notify_payload) + 16);
          notify->doi = IPSEC_DOI;
          notify->protocol_id = PROTO_ISAKMP;
          notify->spi_size = 16;
          notify->notify_message = INITIAL_CONTACT;
          GetCookies((UINT32 *)((UINT8 *)notify + sizeof(notify_payload)));
        }
      }
      // Reset state and retransmision timer, and we're done...
      saState = OAK_MM_KEY_AUTH;
      SetTimer(TIMER_RETRY, saIsakmpTimeout);
      break;

    case OAK_MM_KEY_AUTH:
      // Need to have ID and hash payloads.
      idp = (id_payload *)IsakmpFindPayload(hdr, ISA_ID);
      if (!idp)
        return 0xFFFF;

      if ((saAuthMethod == PRESHRD) && !IsakmpFindPayload(hdr, ISA_HASH))
        return 0xFFFF;

      // We have the right payloads... were they encrypted?
      if ((unsigned char)(hdr->flags & ISAKMP_HDR_ENCR_BIT) == 0)
        return 0xFFFF;
      // Cancel the retransmission timer now.
      CancelTimer();

      // Check out the ID...
      if ((idp->protocol_id && (idp->protocol_id != IPProtoUDP)) ||
          (idp->port && (idp->port != UDPPortISAKMP)) ||
          ((saAuthMethod == PRESHRD) && (idp->id_type != ID_IPV4_ADDR)))
      {
        *delSa = this;
        return INVALID_ID_INFO;
      }
      // Change state so that we don't respond prematurely.
      saState = OAK_AG_NOSTATE;
      // Save the message.
      delete [] saMessage;
      saMessageLength = ntohl(hdr->len);
      saMessage = new UINT8[saMessageLength];
      if (!saMessage)
      {
        localError = NO_MEMORY;
mainfail:
        if (saNewOakVersion)
          error = localError;
        *delSa = this;
        return isaError;
      }
      bcopy((char *)hdr, (char *)saMessage, saMessageLength);
      // Save the IV aside...  This is to cover the case where another
      // (perhaps rogue) message might come in while we're processing
      // async SessionCls calls.  If a rogue message did come in, the
      // act of decrypting it could cause us to lose the real encryptIV
      // value - unless we save it here.
      //!  *((UINT32 *)finalPhaseOneIV) = *((UINT32 *)encryptIV);
      //! *((UINT32 *)finalPhaseOneIV + 1) = *((UINT32 *)encryptIV + 1);
      CopyIV(finalPhaseOneIV, encryptIV);

      if (saAuthMethod == RSA_SIG)
      {
        cert = (cert_payload *)IsakmpFindPayload(hdr, ISA_CERT);
        // Currently, the cert must be X.509 Certificate - Signature;
        // anything else doesn't work.  CES "Version 3" (2.0) puts the
        // cert in as type 1 by mistake, so allow for that.
        //if (!cert || ((cert->cert_spec != 4) && (saCESVersion != 3) &&
        //      (saNewOakVersion != 3)))

        // Allow for pkcs7 and X509 Certificate signature certificate types
        if (!cert || ((cert->cert_spec != CERT_TYPE_PKCS7) &&
                      (cert->cert_spec != CERT_TYPE_X509CERTIFICATE_SIGNATURE)))
        {
          *delSa = this;
          return INVALID_CERT;
        }
        if (!IsakmpFindPayload(hdr, ISA_SIG))
        {
          *delSa = this;
          return INVALID_SIGNATURE;
        }
        cb = new IsakmpCallBackStr;
        if (!cb)
        {
          localError = NO_MEMORY;
          goto mainfail;
        }
        cb->cbSa = this;
        cb->cbSaCookie[0] = saCookie[0];
                cb->cbSaCookie[1] = saCookie[1];
                cb->cbSaCookie[2] = saCookie[2];
                cb->cbSaCookie[3] = saCookie[3];
        cb->cbIndex = IsadbHashFunction(saLocalAddr, saRemoteAddr);
        // Check the ID type, and do the right thing with it...
        switch (idp->id_type)
        {
          case ID_DER_ASN1_DN:
            idData = saMessage + ((UINT8 *)idp - (UINT8 *)hdr) +
                     sizeof(id_payload);
            idLen = ntohs(idp->payload_len) - sizeof(id_payload);
            uidType = SEC_UIDTYPE_ASN1_DN;
            break;

          case ID_IPV4_ADDR:
            // Make sure the ID used matches saRemoteAddr.
            if ((UINT32)saRemoteAddr !=
                *((UINT32 *)((UINT8 *)idp + sizeof(id_payload))))
            {
              delete cb;
              isaError = INVALID_ID_INFO;
              goto mainfail;
            }
            // Move saMessage aside, and build a new buffer to contain
            // the string form of the IP address.  We don't use saRemoteAddr
            // directly, since that could be deleted in mid-call.
            saPreMessage = saMessage;
            saMessage = new UINT8[17];
            if (!saMessage)
            {
              delete cb;
              localError = NO_MEMORY;
              goto mainfail;
            }
            saRemoteAddr.GetAscii((TEXT *)saMessage, 17);
            idData = saMessage;
            idLen = 17;
            uidType = SEC_UIDTYPE_IPADDR_AN;
            break;

          case ID_FQDN:
            saPreMessage = saMessage;
            idLen = ntohs(idp->payload_len) - sizeof(id_payload);
            saMessage = new UINT8[idLen+1];
            if (!saMessage)
            {
              delete cb;
              localError = NO_MEMORY;
              goto mainfail;
            }
            idData = saPreMessage + ((UINT8 *)idp - (UINT8 *)hdr) +
                     sizeof(id_payload);
            bcopy((char *) idData, (char *) saMessage, idLen);
            idData = saMessage;
            idData[idLen] = '\0';
            uidType = SEC_UIDTYPE_FQDN;
            break;

          case ID_USER_FQDN:
            saPreMessage = saMessage;
            idLen = ntohs(idp->payload_len) - sizeof(id_payload);
            saMessage = new UINT8[idLen+1];
            if (!saMessage)
            {
              delete cb;
              localError = NO_MEMORY;
              goto mainfail;
            }
            idData = saPreMessage + ((UINT8 *)idp - (UINT8 *)hdr) +
                     sizeof(id_payload);
            bcopy((char *) idData, (char *) saMessage, idLen);
            idData = saMessage;
            idData[idLen] = '\0';
            uidType = SEC_UIDTYPE_USER_FQDN;
            break;

          default:
            delete cb;
            isaError = INVALID_ID_INFO;
            goto mainfail;
        }
        cb->cbData = (void *)saMessage;
        // Lose the saMessage pointer, so that it doesn't get deleted while
        // the ValidateIdentity() call is underway.  We'll take care of it
        // properly when the async call returns, since it's saved in cbData.
        // Note that we feed saSession in here - if we're the initiator, it'll
        // be filled in; if we're the responder, it'll be zero.
        saMessage = 0;
        localError =
          SessionCls::ValidateIdentity(idData, idLen, uidType,
                                       SEC_TUNNELTYPE_IPSEC,
                                       MainValidateCallBack, (void *)cb,
                                       FALSE, NULL, saSession);
        if (localError != SUCCESS)
        {
          // Need to put saMessage back, so it gets deleted!
          saMessage = (UINT8 *)cb->cbData;
          delete cb;
          goto mainfail;
        }
        // To ensure that saSession survives even if this SA gets deleted
        // while ValidateIdentity() is in progress, we must add a reference
        // to it here, which will be deleted during callback one way or
        // the other.
        if (saSession)
          saSession->AddRef();
      }
      else
      {
        // Need to add a session reference here, too, since the following
        // function will remove it...
        if (saSession)
          saSession->AddRef();
        PostMainModeValidate(saSession, saMessage, 0, SUCCESS);
      }
      // fall through...

    default:
      return 0xFFFF;
  }

  return 0;
}
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 17:12
Оценка:
Здравствуйте, Шахтер, Вы писали:

[]

мда...вот это ужас
Re[6]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Vain Россия google.ru
Дата: 06.02.07 17:15
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

А>>Да господа....

А>>Вам в Армию надо программировать.
АШ>Нет, просто наболело.
"Если сердишься, значит — не прав" (с) Путин
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: [папа STL] Alexander Stepanov "Notes on Programming"
От: creatman Германия  
Дата: 06.02.07 17:56
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, Шахтер, Вы писали:


КЛ>[]


КЛ>+1


КЛ>Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.


Я встречал код где в каждом методе класса было не более чем 10 строчек, смотрелось очень элегантно, учитывая что методов порядка 30 было


Re[7]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 17:57
Оценка: :)
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, Анатолий Широков, Вы писали:


А>>>Да господа....

А>>>Вам в Армию надо программировать.
АШ>>Нет, просто наболело.
V>"Если сердишься, значит — не прав" (с) Путин

вообще-то

"Ты сердишься Юпитер, значит ты неправ." (с) Прометей Зевсу.
Re[4]: [папа STL] Alexander Stepanov "Notes on Programming"
От: Константин Л. Франция  
Дата: 06.02.07 18:00
Оценка:
Здравствуйте, creatman, Вы писали:

C>Здравствуйте, Константин Л., Вы писали:


КЛ>>Здравствуйте, Шахтер, Вы писали:


КЛ>>[]


КЛ>>+1


КЛ>>Но вот 20 строк не всегда получается. Имхо это иногда даже вредно.


C>Я встречал код где в каждом методе класса было не более чем 10 строчек, смотрелось очень элегантно, учитывая что методов порядка 30 было


это все понятно. Просто надо знать меру. Если стоит выбор м/у написанием 2 методов на 20 строк каждый, которые принимают по 10 параметров, я напишу 1, кот принимает 5 параметров. Если он конечно останется тамким же general, как те 2.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.