home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / network / nsclilib / ni_msg.c < prev    next >
Encoding:
Text File  |  1995-12-17  |  108.6 KB  |  3,728 lines  |  [TEXT/R*ch]

  1. /*      
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE                          
  5. *               National Center for Biotechnology Information
  6. *                                                                          
  7. *  This software/database is a "United States Government Work" under the   
  8. *  terms of the United States Copyright Act.  It was written as part of    
  9. *  the author's official duties as a United States Government employee and 
  10. *  thus cannot be copyrighted.  This software/database is freely available 
  11. *  to the public for use. The National Library of Medicine and the U.S.    
  12. *  Government have not placed any restriction on its use or reproduction.  
  13. *                                                                          
  14. *  Although all reasonable efforts have been taken to ensure the accuracy  
  15. *  and reliability of the software and data, the NLM and the U.S.          
  16. *  Government do not and cannot warrant the performance or results that    
  17. *  may be obtained by using this software or data. The NLM and the U.S.    
  18. *  Government disclaim all warranties, express or implied, including       
  19. *  warranties of performance, merchantability or fitness for any particular
  20. *  purpose.                                                                
  21. *                                                                          
  22. *  Please cite the author in any work or product based on this material.   
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:    ni_msg.c
  27. *
  28. * Author:       Beatty, Gish, Epstein
  29. *
  30. * Version Creation Date:        1/1/92
  31. *
  32. * $Revision: 1.23 $
  33. *
  34. * File Description: 
  35. *   This file consists mostly of functions for creating, destroying, reading,
  36. *   and writing message structures. It also contains the high-level functions
  37. *   for reading or writing a message, as well as the lowest-level functions
  38. *   which are read, write, and error 'hooks' for the ASN library.
  39. *
  40. * Modifications:  
  41. * --------------------------------------------------------------------------
  42. * Date     Name        Description of modification
  43. * -------  ----------  -----------------------------------------------------
  44. * 5/01/92  Epstein     Added extensive in-line commentary, and removed all tabs
  45. * 5/01/92  Epstein     Modified to support un-blocked reads, by storing state
  46. *                      information and returning to the caller.
  47. * 5/11/92  Epstein     Changed MsgBuild() to free memory in the event of
  48. *                      an invalid message type; fixed MsgDestroy() to
  49. *                      return -1 rather than NULL (NULL is the wrong type);
  50. *                      added logic to allow the dispatcher to update the
  51. *                      CONID file when the value of "conid" is incremented
  52. * 6/18/92  Epstein     Added AsnIoSetBufsize() for write socket, to improve
  53. *                      network throughput.
  54. * 6/22/92  Epstein     Changed all NI_AsnRead() and NI_AsnWrite() error return
  55. *                      codes to be the negative of the absolute value of errno,
  56. *                      because errno's can be negative on Macintoshes.
  57. * 7/10/92  Epstein     Changed MsgSaveData() to set the current index
  58. *                      (mh->cur_index) to match the number of queued bytes;
  59. *                      this avoids unintentional re-reading of queued data
  60. *                      unless a read fails.
  61. * 2/12/93  Epstein     Add an argument to MsgMakeHandle() to indicate whether
  62. *                      or not a socket should be created.
  63. * 2/19/93  Epstein     Add PC-NFS 4.0 support.
  64. * 2/24/93  Epstein     Fix memory leak
  65. * 3/08/93  Epstein     Add optional client platform to service request
  66. * 3/11/93  Epstein     Add "is-alternate-list" boolean to dispatcher-list,
  67. *                      to make it easier for a dispatcher-monitor-client
  68. *                      to distinguish between primary and backup dispatchers.
  69. * 3/23/93  Epstein     Change platform conditional-compilation to include
  70. *                      the NETP_INET_ prefix, add VMS/TGV support.
  71. * 4/02/93  Epstein     Remember to initialize conid to a known value ... this
  72. *                      avoids clients connecting with all sorts of wild conid
  73. *                      values.
  74. * 4/02/93  Epstein     Add preliminary WinSock support.
  75. * 4/13/93  Epstein     Add subSet fields to toolset to support catalog
  76. *                      filtering by dispatcher.
  77. * 4/21/93  Schuler     Removed (IoFuncType) typecast on calls to AsnIoNew()
  78. *                      in order to enable compile-time type checking.
  79. * 4/21/93  Schuler     Changed implementation of NI_AsnNew(), NI_AsnWrite(), and
  80. *                      NI_ASNIOError() to use LIBCALLBACK calling convention.
  81. * 4/21/93  Epstein     Fix MsgBuild() return error (was incorrectly returning
  82. *                      FALSE instead of NULL).
  83. * 5/07/93  Epstein     Fixup NI_SetBlocking() and NI_SetNonBlocking(), which
  84. *                      had been backwards.  Also add Wollongong (TWG) support,
  85. *                      and use INVALID_SOCKET #define, per WinSock spec.
  86. * 5/25/93  Epstein     Add regional support, and add application ID to
  87. *                      service request.
  88. * 5/27/93  Epstein     Provide separate error code for ASN.1 dynamic object
  89. *                      loader failure, try to do separate PeekMessage, etc.
  90. *                      code for WinSock in the never-ending battle to fix
  91. *                      scrollbar behavior under WinSock.
  92. * 5/28/93  Epstein     Re-work Disable-vibrant code to use new pragmatic
  93. *                      "Gestalt" functions, rather than making explicit
  94. *                      calls into Vibrant.  This decouples Network Services
  95. *                      from Vibrant.
  96. * 6/02/93  Epstein     Fixup sys_errlist references to correctly use new
  97. *                      SOCK_INDEX_ERRNO macro, to accomodate yet another
  98. *                      WinSock peculiarity.
  99. * 6/07/93  Epstein     Use new timer mechanism to support "hung timeout";
  100. *                      also add new function MsgSetTimeoutHooks().
  101. *                      Also add missing revision history, derived from
  102. *                      RCS file.
  103. * 6/09/93  Epstein     Added activity hook to report network activity back
  104. *                      to an application.
  105. * 6/15/93  Epstein     Fix long-standing WinSock scrolling problem, by changing
  106. *                      NI_poll_select() to refrain from processing
  107. *                      WM_LBUTTONUP messages.  For some reason, reading these
  108. *                      messages off the queue and processing them resulted
  109. *                      in a failure to correctly interpret the WM_LBUTTONUP
  110. *                      message as an "end scrolling" message.
  111. *                      Also clean-up Windows compilation warnings.
  112. * 6/17/93  Epstein     Temporarily change NI_SetNonBlocking() to provide
  113. *                      incorrect (blocking!) semantics for TWG.  This must
  114. *                      be fixed at a later date.
  115. * 6/22/93  Epstein     Support UCX, although NI_SetNonBlocking() and
  116. *                      NI_SetBlocking() are currently completely unsupported.
  117. *                      This should be fixed at a later date if it turns out
  118. *                      that UCX actually supports these features.
  119. * 8/09/93  Epstein     Remove annoying cursor modification, except for NEWT,
  120. *                      where it may be necessary.
  121. *
  122. * ==========================================================================
  123. */
  124.  
  125. #include <ncbi.h>
  126. #include "ni_msg.h"
  127. #include "ni_asn.h"   /* produced by ASNTOOL */
  128. #ifdef OS_MAC
  129. #include <s_fcntl.h>
  130. #include <neterrno.h> /* missing error numbers on Mac */
  131. #endif /* OS_MAC */
  132. #ifdef OS_VMS
  133. #include <perror.h>
  134. #endif /* OS_VMS */
  135.  
  136. /* macros */
  137. #if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
  138. #define DisabVibrant() { Nlm_SetGestaltValue(1,1); SetHourGlass(); }
  139. #define EnabVibrant()  { Nlm_ClearGestaltValue(1); PopHourGlass(); }
  140. #else
  141. #define DisabVibrant() 
  142. #define EnabVibrant()
  143. #endif /* NETP_INET_NEWT */
  144.  
  145. static NIAckPtr                 readACK PROTO((void));
  146. static void                     writeACK PROTO((NIAckPtr ackp));
  147. static NINackPtr                readNACK PROTO((void));
  148. static void                     writeNACK PROTO((NINackPtr nackp));
  149. static NILoginPtr               readLOGIN PROTO ((void));
  150. static void                     writeLOGIN PROTO((NILoginPtr loginp));
  151. static NISvcListPtr             readSVC_LIST PROTO ((void));
  152. static void                     writeSVC_LIST PROTO((NISvcListPtr svclistp));
  153. static NISvcReqPtr              readSVC_REQUEST PROTO ((void));
  154. static void                     writeSVC_REQUEST PROTO((NISvcReqPtr svcreqp));
  155. static NISvcRespPtr             readSVC_RESPONSE PROTO ((void));
  156. static void                     writeSVC_RESPONSE PROTO((NISvcRespPtr svcrespp));
  157. static NICmdPtr                 readCOMMAND PROTO ((void));
  158. static void                     writeCOMMAND PROTO((NICmdPtr cmdp));
  159. static NIAcctPtr                readACCT PROTO ((void));
  160. static void                     writeACCT PROTO((NIAcctPtr accp));
  161. static NICatalogPtr             readCATALOG PROTO ((void));
  162. static void                     writeCATALOG PROTO((NICatalogPtr catp));
  163.  
  164. static int                      readRequest PROTO ((ReqPtr rp));
  165. static void                     writeRequest PROTO((ReqPtr reqp));
  166. static int                      readUid PROTO ((NI_UidPtr uid));
  167. static void                     writeUid PROTO((NI_UidPtr uidp));
  168. static int                      readService PROTO ((NISvcPtr svcp));
  169. static void                     writeService PROTO((NISvcPtr svcp));
  170. static int                      readResource PROTO ((NIResPtr resp));
  171. static void                     writeResource PROTO((NIResPtr resp));
  172. static int                      readRegion PROTO ((NIRegionPtr regp));
  173. static void                     writeRegion PROTO((NIRegionPtr regp));
  174. static int                      readToolset PROTO ((NIToolsetPtr tsp));
  175. static void                     writeToolset PROTO((NIToolsetPtr tsp));
  176. static int                      readDispInfo PROTO ((NIDispInfoPtr dip));
  177. static void                     writeDispInfo PROTO((NIDispInfoPtr dip));
  178.  
  179. static Boolean                  InitMsg PROTO((void));
  180. static void                     WriteCleanup PROTO((CharPtr tmpbuf));
  181. static Boolean                  MsgHaveSavedData PROTO((MHandPtr mh));
  182. static void                     MsgSaveData PROTO((MHandPtr mh, CharPtr buf,
  183.                                                    Uint2 len));
  184. static int                      MsgReadSavedData PROTO((MHandPtr mh,
  185.                                                    CharPtr buf, Uint2 len));
  186. static void                     MsgFreeSavedData PROTO((MHandPtr mh));
  187. static void                     SetHourGlass PROTO((void));
  188. static void                     PopHourGlass PROTO((void));
  189.  
  190.  
  191. /* VARS */
  192.  
  193. Uint4           conid = 1;      /* globally unique connection ID counter */
  194. Jumpbuf         ni_env;         /* saved environment for LongJump (servers only) */
  195.  
  196. static AsnTypePtr       atp;
  197. static AsnIoPtr         aip;
  198.  
  199.  
  200.  
  201. /* FUNCTIONS */
  202.  
  203. /******************************************************************************/
  204. /*                                                                            */
  205. /* Functions for creating, destroying, reading, and writing message structures*/
  206. /*                                                                            */
  207. /******************************************************************************/
  208.  
  209.  
  210.  
  211.  
  212. /************************************ ACK *************************************/
  213.  
  214. NIAckPtr 
  215. NI_MakeMsgAck(void)
  216. {
  217.     NIAckPtr    ap;
  218.     
  219.     ap = (NIAckPtr) MemNew(sizeof(NIAck));
  220.     ap->seqno = 0;
  221.     ap->dispinfo = NULL;
  222.     return ap;
  223. } /* NI_MakeMsgAck */
  224.  
  225.  
  226. Int2 
  227. NI_DestroyMsgAck(NIAckPtr mp)
  228. {
  229.     if (mp == NULL)
  230.         return 1;
  231.     if (mp->dispinfo != NULL)
  232.     {
  233.         NI_DestroyDispInfo(mp->dispinfo);
  234.     }
  235.     MemFree(mp);
  236.     return 0;
  237. } /* NI_MakeMsgAck */
  238.  
  239.  
  240. static NIAckPtr 
  241. readACK(void)
  242. {
  243.     DataVal     value;
  244.     NIAckPtr    ackp;
  245.     
  246.     ackp = NI_MakeMsgAck();
  247.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  248.         goto AckFail;
  249.     if (AsnReadVal(aip, atp, &value) < 0)
  250.         goto AckFail;
  251.     ackp->seqno = value.intvalue;
  252.     atp = AsnReadId(aip, amp, atp);
  253.     if (atp == MSG_ACK_disp_info) {
  254.         if (AsnReadVal(aip, atp, &value) < 0)
  255.             goto AckFail;
  256.         ackp->dispinfo = NI_MakeDispInfo();
  257.         if (readDispInfo(ackp->dispinfo) < 0)
  258.             goto AckFail;
  259.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  260.             goto AckFail;
  261.     }
  262.     if (atp != MESSAGE_ack)
  263.         goto AckFail;
  264.     if (AsnReadVal(aip, atp, &value) < 0)
  265.         goto AckFail;
  266.     return ackp;
  267.  
  268.   AckFail:
  269.     NI_DestroyMsgAck(ackp);
  270.     return NULL;
  271. } /* readACK */
  272.  
  273.  
  274. static void 
  275. writeACK(NIAckPtr ackp)
  276. {
  277.     DataVal     value;
  278.  
  279.     AsnStartStruct(aip, MESSAGE_ack);
  280.     value.intvalue = (Int4) ackp->seqno;
  281.     AsnWrite(aip, MSG_ACK_seqno, &value);
  282.     if (ackp->dispinfo != NULL) {
  283.         AsnStartStruct(aip, MSG_ACK_disp_info);
  284.         writeDispInfo(ackp->dispinfo);
  285.         AsnEndStruct(aip, MSG_ACK_disp_info);
  286.     }
  287.  
  288.     AsnEndStruct(aip, MESSAGE_ack);
  289. } /* writeACK */
  290.  
  291.  
  292. /************************************ NACK ***********************************/
  293.  
  294. NINackPtr 
  295. NI_MakeMsgNack(void)
  296. {
  297.     NINackPtr   np;
  298.     
  299.     np = (NINackPtr) MemNew(sizeof(NINack));
  300.     np->seqno = 0;
  301.     np->reason = NULL;
  302.     np->dispinfo = NULL;
  303.     return np;
  304. } /* NI_MakeMsgNack */
  305.  
  306.  
  307. Int2 
  308. NI_DestroyMsgNack(NINackPtr mp)
  309. {
  310.     if (mp == NULL)
  311.         return 1;
  312.     if (mp->reason != NULL)
  313.         MemFree(mp->reason);
  314.     if (mp->dispinfo != NULL)
  315.         NI_DestroyDispInfo(mp->dispinfo);
  316.     MemFree(mp);
  317.     return 0;
  318. } /* NI_DestroyMsgNack */
  319.  
  320.  
  321. static NINackPtr 
  322. readNACK(void)
  323. {
  324.     DataVal     value;
  325.     NINackPtr   nackp;
  326.     
  327.     nackp = NI_MakeMsgNack();
  328.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  329.         goto NackFail;
  330.     if (AsnReadVal(aip, atp, &value) < 0)
  331.         goto NackFail;
  332.     nackp->seqno = value.intvalue;
  333.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* code */
  334.         goto NackFail;
  335.     if (AsnReadVal(aip, atp, &value) < 0)
  336.         goto NackFail;
  337.     nackp->code = (NI_Error) value.intvalue;
  338.     
  339.     if ((atp = AsnReadId(aip, amp, atp)) == MSG_NACK_reason) {  /* reason */
  340.         if (AsnReadVal(aip, atp, &value) < 0)
  341.             goto NackFail;
  342.         nackp->reason = (CharPtr) value.ptrvalue;
  343.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  344.             goto NackFail;
  345.     }
  346.     if (atp == MSG_NACK_disp_info) {
  347.         if (AsnReadVal(aip, atp, &value) < 0)
  348.             goto NackFail;
  349.         nackp->dispinfo = NI_MakeDispInfo();
  350.         if (readDispInfo(nackp->dispinfo) < 0)
  351.             goto NackFail;
  352.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  353.             goto NackFail;
  354.     }
  355.     if (atp != MESSAGE_nack)
  356.         goto NackFail;
  357.     if (AsnReadVal(aip, atp, &value) < 0)
  358.         goto NackFail;
  359.     return nackp;
  360.  
  361.   NackFail:
  362.     NI_DestroyMsgNack(nackp);
  363.     return NULL;
  364. } /* readNACK */
  365.  
  366.  
  367. static void 
  368. writeNACK(NINackPtr nackp)
  369. {
  370.     DataVal     value;
  371.  
  372.     AsnStartStruct(aip, MESSAGE_nack);
  373.     value.intvalue = (Int4) nackp->seqno;
  374.     AsnWrite(aip, MSG_NACK_seqno, &value);
  375.     value.intvalue = (Int4) nackp->code;
  376.     AsnWrite(aip, MSG_NACK_code, &value);
  377.     
  378.     if (nackp->reason != NULL) {
  379.         value.ptrvalue = (Pointer) nackp->reason;
  380.         AsnWrite(aip, MSG_NACK_reason, &value);
  381.     }
  382.     if (nackp->dispinfo != NULL) {
  383.         AsnStartStruct(aip, MSG_NACK_disp_info);
  384.         writeDispInfo(nackp->dispinfo);
  385.         AsnEndStruct(aip, MSG_NACK_disp_info);
  386.     }
  387.     AsnEndStruct(aip, MESSAGE_nack);
  388. }
  389.  
  390.  
  391. /************************************ LOGIN ***********************************/
  392.  
  393. NILoginPtr 
  394. NI_MakeMsgLogin(void)
  395. {
  396.     NILoginPtr  lp;
  397.     
  398.     lp = (NILoginPtr) MemNew(sizeof(NILogin));
  399.     lp->seqno = 0;
  400.     lp->uid = NI_MakeUid();
  401.     lp->password = NULL;
  402.     lp->dispserialno = -1;
  403.     return lp;
  404. } /* NI_MakeMsgLogin() */
  405.  
  406.  
  407. Int2 
  408. NI_DestroyMsgLogin(NILoginPtr lp)
  409. {
  410.     if (lp == NULL)
  411.         return 1;
  412.     if (lp->uid != NULL)
  413.         NI_DestroyUid(lp->uid);
  414.     if (lp->password != NULL)
  415.         MemFree(lp->password);
  416.     MemFree(lp);
  417.     return 0;
  418. } /* NI_DestroyMsgLogin() */
  419.  
  420.  
  421. static NILoginPtr 
  422. readLOGIN(void)
  423. {
  424.     DataVal     value;
  425.     NILoginPtr  loginp;
  426.     
  427.     loginp = NI_MakeMsgLogin();
  428.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* seqno */
  429.         goto LoginFail;
  430.     if (AsnReadVal(aip, atp, &value) < 0)
  431.         goto LoginFail;
  432.     loginp->seqno = value.intvalue;
  433.     
  434.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_LOGIN_uid */
  435.         goto LoginFail;
  436.     if (AsnReadVal(aip, atp, &value) < 0)
  437.         goto LoginFail;
  438.     if (readUid(loginp->uid) < 0)
  439.         goto LoginFail;
  440.     
  441.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* password ? */
  442.         goto LoginFail;
  443.  
  444.     if (atp == MSG_LOGIN_password) {
  445.         if (AsnReadVal(aip, atp, &value) < 0)
  446.             goto LoginFail;
  447.         loginp->password = (CharPtr) value.ptrvalue;
  448.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  449.             goto LoginFail;
  450.     }
  451.     
  452.     if (atp == MSG_LOGIN_disp_serial_no) {
  453.         if (AsnReadVal(aip, atp, &value) < 0)
  454.             goto LoginFail;
  455.         loginp->dispserialno = value.intvalue;
  456.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  457.             goto LoginFail;
  458.     }
  459.     
  460.     if (atp != MESSAGE_login)
  461.         goto LoginFail;
  462.     if (AsnReadVal(aip, atp, &value) < 0)
  463.         goto LoginFail;
  464.     return loginp;
  465.  
  466.   LoginFail:
  467.     NI_DestroyMsgLogin(loginp);
  468.     return NULL;
  469. } /* readLOGIN */
  470.  
  471.  
  472. static void 
  473. writeLOGIN(NILoginPtr loginp)
  474. {
  475.     DataVal     value;
  476.  
  477.     AsnStartStruct(aip, MESSAGE_login);
  478.     value.intvalue = (Int4) loginp->seqno;
  479.     AsnWrite(aip, MSG_LOGIN_seqno, &value);
  480.     AsnStartStruct(aip, MSG_LOGIN_uid);
  481.     writeUid(loginp->uid);
  482.     AsnEndStruct(aip, MSG_LOGIN_uid);
  483.     
  484.     if (loginp->password != NULL) {
  485.         value.ptrvalue = (Pointer) loginp->password;
  486.         AsnWrite(aip, MSG_LOGIN_password, &value);
  487.     }
  488.     if (loginp->dispserialno >= 0) {
  489.         value.intvalue = loginp->dispserialno;
  490.         AsnWrite(aip, MSG_LOGIN_disp_serial_no, &value);
  491.     }
  492.     AsnEndStruct(aip, MESSAGE_login);
  493. } /* writeLOGIN */
  494.  
  495.  
  496. /************************************ SVC_LIST ********************************/
  497.  
  498. NISvcListPtr 
  499. NI_MakeMsgSvclist(void)
  500. {
  501.     NISvcListPtr        sp;
  502.     
  503.     sp = (NISvcListPtr) MemNew(sizeof(NISvcList));
  504.     sp->seqno = 0;
  505.     sp->toolset = NI_MakeToolset();
  506.     return sp;
  507. } /* NI_MakeMsgSvclist */
  508.  
  509.  
  510. Int2 
  511. NI_DestroyMsgSvclist(NISvcListPtr sp)
  512. {
  513.     if (sp == NULL)
  514.         return 1;
  515.     if (sp->toolset != NULL)
  516.         NI_DestroyToolset(sp->toolset);
  517.     MemFree(sp);
  518.     return 0;
  519. } /* NI_DestroyMsgSvclist */
  520.  
  521.  
  522. static NISvcListPtr 
  523. readSVC_LIST(void)
  524. {
  525.     DataVal     value;
  526.     NISvcListPtr        svclistp;
  527.     
  528.     svclistp = NI_MakeMsgSvclist();
  529.     
  530.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_LIST_seqno */
  531.         goto SvcListFail;
  532.     if (AsnReadVal(aip, atp, &value) < 0)
  533.         goto SvcListFail;
  534.     svclistp->seqno = value.intvalue;
  535.     
  536.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_LIST_toollist */
  537.         goto SvcListFail;
  538.     if (AsnReadVal(aip, atp, &value) < 0)
  539.         goto SvcListFail;
  540.     if (readToolset(svclistp->toolset) < 0)
  541.         goto SvcListFail;
  542.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  543.         goto SvcListFail;
  544.     if (AsnReadVal(aip, atp, &value) < 0)
  545.         goto SvcListFail;
  546.     
  547.     if (atp != MESSAGE_svc_list)
  548.         goto SvcListFail;
  549.     return svclistp;
  550.  
  551.   SvcListFail:
  552.     NI_DestroyMsgSvclist(svclistp);
  553.     return NULL;
  554. } /* readSVC_LIST */
  555.  
  556.  
  557. static void 
  558. writeSVC_LIST(NISvcListPtr svclistp)
  559. {
  560.     DataVal     value;
  561.  
  562.     AsnStartStruct(aip, MESSAGE_svc_list);
  563.     value.intvalue = (Int4) svclistp->seqno;
  564.     AsnWrite(aip, MSG_SVC_LIST_seqno, &value);
  565.     
  566.     AsnStartStruct(aip, MSG_SVC_LIST_toollist);
  567.     writeToolset(svclistp->toolset);
  568.     AsnEndStruct(aip, MSG_SVC_LIST_toollist);
  569.     
  570.     AsnEndStruct(aip, MESSAGE_svc_list);
  571. } /* writeSVC_LIST */
  572.  
  573.  
  574. /************************************ SVC_REQUEST *****************************/
  575.  
  576. NISvcReqPtr 
  577. NI_MakeMsgSvcreq(void)
  578. {
  579.     NISvcReqPtr sp;
  580.     
  581.     sp = (NISvcReqPtr) MemNew(sizeof(NISvcReq));
  582.     sp->seqno = 0;
  583.     sp->uid = NI_MakeUid();
  584.     sp->request = NI_MakeRequest();
  585.     sp->platform = NI_PLATFORM_UNKNOWN;
  586.     sp->applId = NULL;
  587.     return sp;
  588. } /* NI_MakeMsgSvcreq() */
  589.  
  590.  
  591. Int2 
  592. NI_DestroyMsgSvcreq(NISvcReqPtr sp)
  593. {
  594.     if (sp == NULL)
  595.         return 1;
  596.     if (sp->uid != NULL)
  597.         NI_DestroyUid(sp->uid);
  598.     if (sp->request != NULL)
  599.         NI_DestroyRequest(sp->request);
  600.     if (sp->applId != NULL)
  601.         MemFree(sp->applId);
  602.     MemFree(sp);
  603.     return 0;
  604. } /* NI_DestroyMsgSvcreq() */ 
  605.  
  606.  
  607. static NISvcReqPtr 
  608. readSVC_REQUEST(void)
  609. {
  610.     DataVal     value;
  611.     NISvcReqPtr svcreqp;
  612.     
  613.     svcreqp = NI_MakeMsgSvcreq();
  614.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_seqno */
  615.         goto SvcReqFail;
  616.     if (AsnReadVal(aip, atp, &value) < 0)
  617.         goto SvcReqFail;
  618.     svcreqp->seqno = value.intvalue;
  619.     
  620.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_conid */
  621.         goto SvcReqFail;
  622.     if (AsnReadVal(aip, atp, &value) < 0)
  623.         goto SvcReqFail;
  624.     svcreqp->conid = value.intvalue;
  625.     
  626.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_uid */
  627.         goto SvcReqFail;
  628.     if (AsnReadVal(aip, atp, &value) < 0)
  629.         goto SvcReqFail;
  630.     if (readUid(svcreqp->uid) < 0)
  631.         goto SvcReqFail;
  632.  
  633.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_request */
  634.         goto SvcReqFail;
  635.     if (AsnReadVal(aip, atp, &value) < 0)
  636.         goto SvcReqFail;
  637.     if (readRequest(svcreqp->request) < 0)
  638.         goto SvcReqFail;
  639.  
  640.     if ((atp = AsnReadId(aip, amp, atp)) == MSG_SVC_REQUEST_platform) {
  641.         if (AsnReadVal(aip, atp, &value) < 0)
  642.             goto SvcReqFail;
  643.         svcreqp->platform = (Uint4) value.intvalue;
  644.         atp = AsnReadId(aip, amp, atp);
  645.     }
  646.  
  647.     if (atp == MSG_SVC_REQUEST_appl_id) {
  648.         if (AsnReadVal(aip, atp, &value) < 0)
  649.             goto SvcReqFail;
  650.         svcreqp->applId = (CharPtr) value.ptrvalue;
  651.         atp = AsnReadId(aip, amp, atp);
  652.     }
  653.  
  654.     if (atp != MESSAGE_svc_request)
  655.         goto SvcReqFail;
  656.     if (AsnReadVal(aip, atp, &value) < 0)
  657.         goto SvcReqFail;
  658.     return svcreqp;
  659.  
  660.   SvcReqFail:
  661.     NI_DestroyMsgSvcreq(svcreqp);
  662.     return NULL;
  663. } /* readSVC_REQUEST */
  664.  
  665.  
  666. static void 
  667. writeSVC_REQUEST(NISvcReqPtr svcreqp)
  668. {
  669.     DataVal     value;
  670.  
  671.     AsnStartStruct(aip, MESSAGE_svc_request);
  672.     value.intvalue = (Int4) svcreqp->seqno;
  673.     AsnWrite(aip, MSG_SVC_REQUEST_seqno, &value);
  674.     value.intvalue = (Int4) svcreqp->conid;
  675.     AsnWrite(aip, MSG_SVC_REQUEST_conid, &value);
  676.     AsnStartStruct(aip, MSG_SVC_REQUEST_uid);
  677.     writeUid(svcreqp->uid);
  678.     AsnEndStruct(aip, MSG_SVC_REQUEST_uid);
  679.     AsnStartStruct(aip, MSG_SVC_REQUEST_request);
  680.     writeRequest(svcreqp->request);
  681.     AsnEndStruct(aip, MSG_SVC_REQUEST_request);
  682.     value.intvalue = (Int4) svcreqp->platform;
  683.     AsnWrite(aip, MSG_SVC_REQUEST_platform, &value);
  684.  
  685.     if (svcreqp->applId != NULL)
  686.     {
  687.         value.ptrvalue = (Pointer) svcreqp->applId;
  688.         AsnWrite(aip, MSG_SVC_REQUEST_appl_id, &value);
  689.     }
  690.  
  691.     AsnEndStruct(aip, MESSAGE_svc_request);
  692. } /* writeSVC_REQUEST */
  693.  
  694.  
  695. /********************************* SVC_RESPONSE *******************************/
  696.  
  697. NISvcRespPtr 
  698. NI_MakeMsgSvcresp(void)
  699. {
  700.     NISvcRespPtr        sp;
  701.     
  702.     sp = (NISvcRespPtr) MemNew(sizeof(NISvcResp));
  703.     sp->seqno = 0;
  704.     sp->request = NI_MakeRequest();
  705.     return sp;
  706. } /* NI_MakeMsgSvcresp() */
  707.  
  708.  
  709. Int2 
  710. NI_DestroyMsgSvcresp(NISvcRespPtr sp)
  711. {
  712.     if (sp == NULL)
  713.         return 1;
  714.     if (sp->request != NULL)
  715.         NI_DestroyRequest(sp->request);
  716.     MemFree(sp);
  717.     return 0;
  718. } /* NI_DestroyMsgSvcresp() */ 
  719.  
  720.  
  721. static NISvcRespPtr 
  722. readSVC_RESPONSE(void)
  723. {
  724.     DataVal             value;
  725.     NISvcRespPtr        svcrespp;
  726.     
  727.     svcrespp = NI_MakeMsgSvcresp();
  728.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_RESPONSE_seqno */
  729.         goto SvcRespFail;
  730.     if (AsnReadVal(aip, atp, &value) < 0)
  731.         goto SvcRespFail;
  732.     svcrespp->seqno = value.intvalue;
  733.     
  734.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_RESPONSE_request */
  735.         goto SvcRespFail;
  736.     if (AsnReadVal(aip, atp, &value) < 0)
  737.         goto SvcRespFail;
  738.     if (readRequest(svcrespp->request) < 0)
  739.         goto SvcRespFail;
  740.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_RESPONSE_request */
  741.         goto SvcRespFail;
  742.     if (AsnReadVal(aip, atp, &value) < 0)
  743.         goto SvcRespFail;
  744.     
  745.     if (atp != MESSAGE_svc_response)
  746.         goto SvcRespFail;
  747.     return svcrespp;
  748.  
  749.   SvcRespFail:
  750.     NI_DestroyMsgSvcresp(svcrespp);
  751.     return NULL;
  752. } /* readSVC_RESPONSE */
  753.  
  754.  
  755. static void 
  756. writeSVC_RESPONSE(NISvcRespPtr svcrespp)
  757. {
  758.     DataVal     value;
  759.  
  760.     AsnStartStruct(aip, MESSAGE_svc_response);
  761.     value.intvalue = (Int4) svcrespp->seqno;
  762.     AsnWrite(aip, MSG_SVC_RESPONSE_seqno, &value);
  763.     AsnStartStruct(aip, MSG_SVC_RESPONSE_request);
  764.     writeRequest(svcrespp->request);
  765.     AsnEndStruct(aip, MSG_SVC_RESPONSE_request);
  766.     AsnEndStruct(aip, MESSAGE_svc_response);
  767. } /* writeSVC_RESPONSE */
  768.  
  769.  
  770. /************************************ COMMAND *********************************/
  771.  
  772. NICmdPtr 
  773. NI_MakeMsgCmd(void)
  774. {
  775.     NICmdPtr    cp;
  776.     
  777.     cp = (NICmdPtr) MemNew(sizeof(NICmd));
  778.     cp->seqno = 0;
  779.     return cp;
  780. } /* NI_MakeMsgCmd() */
  781.  
  782.  
  783. Int2 
  784. NI_DestroyMsgCmd(NICmdPtr cp)
  785. {
  786.     if (cp == NULL)
  787.         return 1;
  788.     MemFree(cp);
  789.     return 0;
  790. } /* NI_DestroyMsgCmd() */ 
  791.  
  792.  
  793. static NICmdPtr 
  794. readCOMMAND(void)
  795. {
  796.     DataVal     value;
  797.     NICmdPtr    cmdp;
  798.     
  799.     cmdp = NI_MakeMsgCmd();
  800.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  801.         goto CmdFail;
  802.     if (AsnReadVal(aip, atp, &value) < 0)
  803.         goto CmdFail;
  804.     cmdp->seqno = value.intvalue;
  805.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* command */
  806.         goto CmdFail;
  807.     if (AsnReadVal(aip, atp, &value) < 0)
  808.         goto CmdFail;
  809.     cmdp->code = (MsgCommand) value.intvalue;
  810.     if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_command)
  811.         goto CmdFail;
  812.     if (AsnReadVal(aip, atp, &value) < 0)
  813.         goto CmdFail;
  814.     return cmdp;
  815.  
  816.   CmdFail:
  817.     NI_DestroyMsgCmd(cmdp);
  818.     return NULL;
  819. } /* readCOMMAND */
  820.  
  821.  
  822. static void 
  823. writeCOMMAND(NICmdPtr cmdp)
  824. {
  825.     DataVal     value;
  826.  
  827.     AsnStartStruct(aip, MESSAGE_command);
  828.     value.intvalue = (Int4) cmdp->seqno;
  829.     AsnWrite(aip, MSG_CMD_seqno, &value);
  830.     value.intvalue = (Int4) cmdp->code;
  831.     AsnWrite(aip, MSG_CMD_command, &value);
  832.     AsnEndStruct(aip, MESSAGE_command);
  833. } /* writeCOMMAND */
  834.  
  835.  
  836. /************************************ ACCT ************************************/
  837.  
  838. NIAcctPtr 
  839. NI_MakeMsgAcct(void)
  840. {
  841.     NIAcctPtr   ap;
  842.     
  843.     ap = (NIAcctPtr) MemNew(sizeof(NIAcct));
  844.     ap->seqno = 0;
  845.     ap->jobname = NULL;
  846.     return ap;
  847. } /* NI_MakeMsgAcct() */
  848.  
  849.  
  850. Int2 
  851. NI_DestroyMsgAcct(NIAcctPtr ap)
  852. {
  853.     if (ap == NULL)
  854.         return 1;
  855.     if (ap->jobname != NULL)
  856.         MemFree(ap->jobname);
  857.     MemFree(ap);
  858.     return 0;
  859. } /* NI_DestroyMsgAcct() */
  860.  
  861.  
  862. static NIAcctPtr 
  863. readACCT(void)
  864. {
  865.     DataVal     value;
  866.     NIAcctPtr   accp;
  867.     
  868.     accp = NI_MakeMsgAcct();
  869.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  870.         goto AcctFail;
  871.     if (AsnReadVal(aip, atp, &value) < 0)
  872.         goto AcctFail;
  873.     accp->seqno = value.intvalue;
  874.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* conid */
  875.         goto AcctFail;
  876.     if (AsnReadVal(aip, atp, &value) < 0)
  877.         goto AcctFail;
  878.     accp->conid = value.intvalue;
  879.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* jobname */
  880.         goto AcctFail;
  881.     if (AsnReadVal(aip, atp, &value) < 0)
  882.         goto AcctFail;
  883.     accp->jobname = (CharPtr) value.ptrvalue;
  884.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* usertime */
  885.         goto AcctFail;
  886.     if (AsnReadVal(aip, atp, &value) < 0)
  887.         goto AcctFail;
  888.     accp->usertime = value.intvalue;
  889.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* systemtime */
  890.         goto AcctFail;
  891.     if (AsnReadVal(aip, atp, &value) < 0)
  892.         goto AcctFail;
  893.     accp->systemtime = value.intvalue;
  894.     if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_acct)
  895.         goto AcctFail;
  896.     if (AsnReadVal(aip, atp, &value) < 0)
  897.         goto AcctFail;
  898.     return accp;
  899.  
  900.   AcctFail:
  901.     NI_DestroyMsgAcct(accp);
  902.     return NULL;
  903. } /* NIreadACCT */
  904.  
  905.  
  906. static void 
  907. writeACCT(NIAcctPtr accp)
  908. {
  909.     DataVal     value;
  910.  
  911.     AsnStartStruct(aip, MESSAGE_acct);
  912.     value.intvalue = (Int4) accp->seqno;
  913.     AsnWrite(aip, MSG_ACCT_seqno, &value);
  914.     value.intvalue = (Int4) accp->conid;
  915.     AsnWrite(aip, MSG_ACCT_conid, &value);
  916.     value.ptrvalue = (Pointer) accp->jobname;
  917.     AsnWrite(aip, MSG_ACCT_jobname, &value);
  918.     value.intvalue = (Int4) accp->usertime;
  919.     AsnWrite(aip, MSG_ACCT_usertime, &value);
  920.     value.intvalue = (Int4) accp->systemtime;
  921.     AsnWrite(aip, MSG_ACCT_systemtime, &value);
  922.     AsnEndStruct(aip, MESSAGE_acct);
  923. } /* NIwriteACCT */
  924.  
  925.  
  926. /************************************ CATALOG *********************************/
  927.  
  928. NICatalogPtr 
  929. NI_MakeMsgCatalog(void)
  930. {
  931.     NICatalogPtr        cp;
  932.     
  933.     cp = (NICatalogPtr) MemNew(sizeof(NICatalog));
  934.     cp->motd = NULL;
  935.     cp->toolsetL = NULL;
  936.     return cp;
  937. } /* NI_MakeCatalog */
  938.  
  939.  
  940. Int2 
  941. NI_DestroyMsgCatalog(NICatalogPtr cp)
  942. {
  943.     NodePtr             np;
  944.     
  945.     
  946.     if (cp == NULL)
  947.         return 1;
  948.     if (cp->motd != NULL)
  949.         MemFree(cp->motd);
  950.     if ((np = cp->toolsetL) != NULL) {
  951.         do {
  952.             NI_DestroyToolset((NIToolsetPtr) np->elem);
  953.             np = ListDelete(np);
  954.         } while (np != NULL);
  955.     }   
  956.     MemFree(cp);
  957.     return 0;
  958. } /* NI_DestroyMsgCatalog */
  959.  
  960.  
  961. static NICatalogPtr 
  962. readCATALOG(void)
  963. {
  964.     DataVal     value;
  965.     NICatalogPtr        catp;
  966.     NIToolsetPtr        tsp;
  967.     
  968.     catp = NI_MakeMsgCatalog();
  969.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_CATALOG_seqno */
  970.         goto CatalogFail;
  971.     if (AsnReadVal(aip, atp, &value) < 0)
  972.         goto CatalogFail;
  973.     catp->seqno = value.intvalue;
  974.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  975.         goto CatalogFail;
  976.     
  977.     if (atp == MSG_CATALOG_motd) {              /* MSG_CATALOG_motd ? */
  978.         if (AsnReadVal(aip, atp, &value) < 0)
  979.             goto CatalogFail;
  980.         catp->motd = (CharPtr) value.ptrvalue;
  981.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  982.             goto CatalogFail;
  983.     }
  984.     
  985.     if (atp == MSG_CATALOG_toollists) {         /* MSG_CATALOG_toollists ? */
  986.         if (AsnReadVal(aip, atp, &value) < 0)
  987.             goto CatalogFail;
  988.         while ((atp = AsnReadId(aip, amp, atp)) == MSG_CATALOG_toollists_E) {
  989.             if (AsnReadVal(aip, atp, &value) < 0)
  990.                 goto CatalogFail;
  991.             tsp = NI_MakeToolset();
  992.             if (readToolset(tsp) < 0)
  993.                 goto CatalogFail;
  994.             ListBreakRing(tsp->services);
  995.             ListBreakRing(tsp->resources);
  996.             catp->toolsetL = ListInsert((VoidPtr) tsp, catp->toolsetL); /* end of list */
  997.         }
  998.         if (atp == NULL)
  999.             goto CatalogFail;
  1000.         catp->toolsetL = catp->toolsetL->next;          /* point to first */
  1001.         if (AsnReadVal(aip, atp, &value) < 0)           /* MSG_CATALOG_toollists */
  1002.             goto CatalogFail;
  1003.         ListBreakRing(catp->toolsetL);
  1004.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1005.             goto CatalogFail;
  1006.     }
  1007.     
  1008.     if (atp != MESSAGE_catalog)
  1009.         goto CatalogFail;
  1010.     if (AsnReadVal(aip, atp, &value) < 0)
  1011.         goto CatalogFail;
  1012.     return catp;
  1013.  
  1014.   CatalogFail:
  1015.     NI_DestroyMsgCatalog(catp);
  1016.     return NULL;
  1017. } /* readCATALOG */
  1018.  
  1019.  
  1020. static void 
  1021. writeCATALOG(NICatalogPtr catp)
  1022. {
  1023.     DataVal     value;
  1024.     NodePtr     np, lastnode;
  1025.     
  1026.     AsnStartStruct(aip, MESSAGE_catalog);
  1027.     value.intvalue = (Int4) catp->seqno;
  1028.     AsnWrite(aip, MSG_CATALOG_seqno, &value);
  1029.     if (catp->motd != NULL) {
  1030.         value.ptrvalue = (Pointer) catp->motd;
  1031.         AsnWrite(aip, MSG_CATALOG_motd, &value);
  1032.     }
  1033.     
  1034.     np = catp->toolsetL;
  1035.     if (np != NULL) {
  1036.         AsnStartStruct(aip, MSG_CATALOG_toollists);
  1037.         lastnode = np->last;
  1038.         while (np != NULL) {
  1039.             AsnStartStruct(aip, MSG_CATALOG_toollists_E);
  1040.             writeToolset((NIToolsetPtr) np->elem);
  1041.             AsnEndStruct(aip, MSG_CATALOG_toollists_E);
  1042.             if (np == lastnode)
  1043.                 break;
  1044.             np = np->next;
  1045.         }
  1046.         AsnEndStruct(aip, MSG_CATALOG_toollists);
  1047.     }
  1048.     
  1049.     AsnEndStruct(aip, MESSAGE_catalog);
  1050. } /* writeCatalog */
  1051.  
  1052.  
  1053. /************************************ REQUEST *********************************/
  1054.  
  1055. ReqPtr
  1056. NI_MakeRequest(void)
  1057. {
  1058.     ReqPtr              rp;
  1059.     
  1060.     rp = (ReqPtr) MemNew(sizeof(Request));
  1061.     rp->clientAddr = NULL;
  1062.     rp->clientPort = 0;
  1063.     rp->service = NI_MakeService();
  1064.     rp->resourceL = NULL;
  1065.     return(rp);
  1066. } /* NI_MakeRequest() */
  1067.  
  1068.  
  1069. Int2
  1070. NI_DestroyRequest(ReqPtr rp)
  1071. {
  1072.     if (rp == NULL)
  1073.         return 1;
  1074.     if (rp->clientAddr != NULL)
  1075.         MemFree(rp->clientAddr);
  1076.     if (rp->service != NULL)
  1077.         NI_DestroyService(rp->service);
  1078.     if (rp->resourceL != NULL) {        /* destroy list of nodes and resources they point to */
  1079.         while (rp->resourceL != NULL) {
  1080.             NI_DestroyResource((NIResPtr)rp->resourceL->elem);
  1081.             rp->resourceL = ListDelete(rp->resourceL);
  1082.         }
  1083.     }
  1084.     MemFree(rp);
  1085.     return 0;
  1086. } /* NI_DestroyRequest() */
  1087.  
  1088.  
  1089. static int
  1090. readRequest(ReqPtr reqp)
  1091. {
  1092.     DataVal     value;
  1093.     NIResPtr    resp;
  1094.     
  1095.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1096.         goto RequestFail;
  1097.     if (atp == REQUEST_address) {               /* REQUEST_address ? */
  1098.         if (AsnReadVal(aip, atp, &value) < 0)
  1099.             goto RequestFail;
  1100.         reqp->clientAddr = (CharPtr) value.ptrvalue;
  1101.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1102.             goto RequestFail;
  1103.     }
  1104.     if (atp == REQUEST_port) {                  /* REQUEST_port ? */
  1105.         if (AsnReadVal(aip, atp, &value) < 0)
  1106.             goto RequestFail;
  1107.         reqp->clientPort = (Uint2) value.intvalue;
  1108.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1109.             goto RequestFail;
  1110.     }
  1111.     if (AsnReadVal(aip, atp, &value) < 0)       /* REQUEST_svcentry */
  1112.         goto RequestFail;
  1113.     if (readService(reqp->service) < 0)
  1114.         goto RequestFail;
  1115.     
  1116.     if ((atp = AsnReadId(aip, amp, atp)) == REQUEST_resentry) {
  1117.         if (AsnReadVal(aip, atp, &value) < 0)
  1118.             goto RequestFail;
  1119.  
  1120.         while ((atp = AsnReadId(aip, amp, atp)) == REQUEST_resentry_E) {
  1121.             if (AsnReadVal(aip, atp, &value) < 0)
  1122.                 goto RequestFail;
  1123.             resp = NI_MakeResource();
  1124.             if (readResource(resp) < 0) {
  1125.                 NI_DestroyResource(resp);
  1126.                 goto RequestFail;
  1127.             }
  1128.             reqp->resourceL = ListInsert((VoidPtr) resp, reqp->resourceL);      /* end of list */
  1129.         }
  1130.         if (atp == NULL)
  1131.             goto RequestFail;
  1132.         reqp->resourceL = reqp->resourceL->next;        /* point to first */
  1133.         if (AsnReadVal(aip, atp, &value) < 0)           /* REQUEST_resentry */
  1134.             goto RequestFail;
  1135.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1136.             goto RequestFail;
  1137.     }
  1138.     if (atp == NULL)
  1139.         goto RequestFail;
  1140.  
  1141.     if (AsnReadVal(aip, atp, &value) < 0)
  1142.         goto RequestFail;
  1143.     return 0;
  1144.  
  1145.   RequestFail:
  1146.     if (reqp->resourceL != NULL) {      /* destroy list of nodes and resources they point to */
  1147.         while (reqp->resourceL != NULL) {
  1148.             NI_DestroyResource((NIResPtr)reqp->resourceL->elem);
  1149.             reqp->resourceL = ListDelete(reqp->resourceL);
  1150.         }
  1151.     }
  1152.     return -1;
  1153. } /* readrequest */
  1154.  
  1155.  
  1156. static void 
  1157. writeRequest(ReqPtr reqp)
  1158. {
  1159.     DataVal     value;
  1160.     NodePtr     np, lastnode;
  1161.     
  1162.     if (reqp->clientAddr != NULL) {
  1163.         value.ptrvalue = (Pointer) reqp->clientAddr;
  1164.         AsnWrite(aip, REQUEST_address, &value);
  1165.     }
  1166.     if (reqp->clientPort != 0) {
  1167.         value.intvalue = (Int4) reqp->clientPort;
  1168.         AsnWrite(aip, REQUEST_port, &value);
  1169.     }
  1170.     AsnStartStruct(aip, REQUEST_svcentry);
  1171.     writeService(reqp->service);
  1172.     AsnEndStruct(aip, REQUEST_svcentry);
  1173.     
  1174.     np = reqp->resourceL;
  1175.     if (np != NULL) {
  1176.         AsnStartStruct(aip, REQUEST_resentry);
  1177.         lastnode = np->last;
  1178.         while (np != NULL) {
  1179.             AsnStartStruct(aip, REQUEST_resentry_E);
  1180.             writeResource((NIResPtr) np->elem);
  1181.             AsnEndStruct(aip, REQUEST_resentry_E);
  1182.             if (np == lastnode)
  1183.                 break;
  1184.             np = np->next;
  1185.         }
  1186.         AsnEndStruct(aip, REQUEST_resentry);
  1187.     }
  1188. } /* writeRequest */
  1189.  
  1190.  
  1191. /************************************ UID *************************************/
  1192.  
  1193. NI_UidPtr 
  1194. NI_MakeUid(void)
  1195. {
  1196.     NI_UidPtr   up;
  1197.     
  1198.     up = (NI_UidPtr) MemNew(sizeof(NI_Uid));
  1199.     up->username = NULL;
  1200.     up->group = NULL;
  1201.     up->domain = NULL;
  1202.     return up;
  1203. } /* NI_MakeUid */
  1204.  
  1205.  
  1206. Int2 
  1207. NI_DestroyUid(NI_UidPtr up)
  1208. {
  1209.     if (up == NULL)
  1210.         return 1;
  1211.     if (up->username != NULL)
  1212.         MemFree(up->username);
  1213.     if (up->group != NULL)
  1214.         MemFree(up->group);
  1215.     if (up->domain != NULL)
  1216.         MemFree(up->domain);
  1217.     MemFree(up);
  1218.     return 0;
  1219. } /* NI_DestroyUid */
  1220.  
  1221.  
  1222. static int 
  1223. readUid(NI_UidPtr uidptr)
  1224. {
  1225.     DataVal     value;
  1226.  
  1227.     if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != IDENTITY_username)           /* username */
  1228.         goto UidFail;
  1229.     if (AsnReadVal(aip, atp, &value) < 0)
  1230.         goto UidFail;
  1231.     uidptr->username = (CharPtr) value.ptrvalue;
  1232.     
  1233.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* group ? */
  1234.         goto UidFail;
  1235.     if (atp == IDENTITY_group) {
  1236.         if (AsnReadVal(aip, atp, &value) < 0)
  1237.             goto UidFail;
  1238.         uidptr->group = (CharPtr) value.ptrvalue;
  1239.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)           /* domain ? */
  1240.             goto UidFail;
  1241.     }
  1242.     if (atp == IDENTITY_domain) {
  1243.         if (AsnReadVal(aip, atp, &value) < 0)
  1244.             goto UidFail;
  1245.         uidptr->domain = (CharPtr) value.ptrvalue;
  1246.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1247.             goto UidFail;
  1248.     }
  1249.     if (AsnReadVal(aip, atp, &value) < 0)
  1250.         goto UidFail;
  1251.     return 0;
  1252.  
  1253.   UidFail:
  1254.     return -1;
  1255. } /* readUid */
  1256.  
  1257.  
  1258. static void 
  1259. writeUid(NI_UidPtr uidptr)
  1260. {
  1261.     DataVal     value;
  1262.     
  1263.     value.ptrvalue = (Pointer) uidptr->username;
  1264.     AsnWrite(aip, IDENTITY_username, &value);
  1265.     
  1266.     if (uidptr->group != NULL) {
  1267.         value.ptrvalue = (Pointer) uidptr->group;
  1268.         AsnWrite(aip, IDENTITY_group, &value);
  1269.     }
  1270.     if (uidptr->domain != NULL) {
  1271.         value.ptrvalue = (Pointer) uidptr->domain;
  1272.         AsnWrite(aip, IDENTITY_domain, &value);
  1273.     }
  1274. } /* writeUid */
  1275.  
  1276.  
  1277. /************************************ SERVICE *********************************/
  1278.  
  1279. NISvcPtr 
  1280. NI_MakeService(void)
  1281. {
  1282.     NISvcPtr    sp;
  1283.     
  1284.     sp = (NISvcPtr) MemNew(sizeof(NIService));
  1285.     sp->name = NULL;
  1286.     sp->minVersion = 0;
  1287.     sp->maxVersion = 0;
  1288.     sp->id = 0;
  1289.     sp->priority = 0;
  1290.     sp->priorityTimeout = 0;
  1291.     sp->priorityPenalty = 0;
  1292.     sp->group = NULL;
  1293.     sp->descrip = NULL;
  1294.     sp->typeL = NULL;
  1295.     return sp;
  1296. } /* NI_MakeService() */
  1297.  
  1298.  
  1299. Int2 
  1300. NI_DestroyService(NISvcPtr sp)
  1301. {
  1302.     if (sp == NULL)
  1303.         return 1;
  1304.     if (sp->name != NULL)
  1305.         MemFree(sp->name);
  1306.     if (sp->group != NULL)
  1307.         MemFree(sp->group);
  1308.     if (sp->descrip != NULL)
  1309.         MemFree(sp->descrip);
  1310.     if (sp->typeL != NULL) { /* destroy list of service types */
  1311.         ListStrDel(sp->typeL);
  1312.     }
  1313.     if (sp->subSetList != NULL) {
  1314.         ListStrDel(sp->subSetList);
  1315.     }
  1316.     if (sp->superSetList != NULL) {
  1317.         ListStrDel(sp->superSetList);
  1318.     }
  1319.  
  1320.     MemFree(sp);
  1321.     return 0;
  1322. } /* NI_DestroyService() */
  1323.  
  1324.  
  1325. static int 
  1326. readService(NISvcPtr svcptr)
  1327. {
  1328.     DataVal     value;
  1329.     CharPtr     svctype;
  1330.  
  1331.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* SVC_ENTRY_name */
  1332.         goto ServiceFail;
  1333.     if (AsnReadVal(aip, atp, &value) < 0)
  1334.         goto ServiceFail;
  1335.     svcptr->name = (CharPtr) value.ptrvalue;
  1336.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* SVC_ENTRY_minvers */
  1337.         goto ServiceFail;
  1338.     if (AsnReadVal(aip, atp, &value) < 0)
  1339.         goto ServiceFail;
  1340.     svcptr->minVersion = (Uint2) value.intvalue;
  1341.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* SVC_ENTRY_maxvers */
  1342.         goto ServiceFail;
  1343.     if (AsnReadVal(aip, atp, &value) < 0)
  1344.         goto ServiceFail;
  1345.     svcptr->maxVersion = (Uint2) value.intvalue;
  1346.     
  1347.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1348.         goto ServiceFail;
  1349.     if (atp == SVC_ENTRY_id) {                          /* SVC_ENTRY_id ? */
  1350.         if (AsnReadVal(aip, atp, &value) < 0)
  1351.             goto ServiceFail;
  1352.         svcptr->id = (Uint2) value.intvalue;
  1353.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1354.             goto ServiceFail;
  1355.     }
  1356.     if (atp == SVC_ENTRY_priority) {                    /* SVC_ENTRY_priority ? */
  1357.         if (AsnReadVal(aip, atp, &value) < 0)
  1358.             goto ServiceFail;
  1359.         svcptr->priority = (Uint2) value.intvalue;
  1360.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1361.             goto ServiceFail;
  1362.     }
  1363.     if (atp == SVC_ENTRY_group) {                       /* SVC_ENTRY_group ? */
  1364.         if (AsnReadVal(aip, atp, &value) < 0)
  1365.             goto ServiceFail;
  1366.         svcptr->group = (CharPtr) value.ptrvalue;
  1367.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1368.             goto ServiceFail;
  1369.     }
  1370.     if (atp == SVC_ENTRY_description) {                 /* SVC_ENTRY_description ? */
  1371.         if (AsnReadVal(aip, atp, &value) < 0)
  1372.             goto ServiceFail;
  1373.         svcptr->descrip = (CharPtr) value.ptrvalue;
  1374.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1375.             goto ServiceFail;
  1376.     }
  1377.     if (atp == SVC_ENTRY_types) {
  1378.         if (AsnReadVal(aip, atp, &value) < 0)
  1379.             goto ServiceFail;
  1380.  
  1381.         /* read the list of service types */
  1382.         while ((atp = AsnReadId(aip, amp, atp)) == SVC_ENTRY_types_E)
  1383.         {
  1384.             if (AsnReadVal(aip, atp, &value) < 0)
  1385.                 goto ServiceFail;
  1386.             svctype = value.ptrvalue;
  1387.             svcptr->typeL = ListInsert((VoidPtr) svctype, svcptr->typeL);
  1388.         }
  1389.         if (atp == NULL)
  1390.             goto ServiceFail;
  1391.         svcptr->typeL = svcptr->typeL->next;            /* point to first */
  1392.         if (AsnReadVal(aip, atp, &value) < 0)           /* SVC_ENTRY_types */
  1393.             goto ServiceFail;
  1394.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1395.             goto ServiceFail;
  1396.     }
  1397.  
  1398.     if (atp == SVC_ENTRY_priority_timeout) {
  1399.         if (AsnReadVal(aip, atp, &value) < 0)
  1400.             goto ServiceFail;
  1401.         svcptr->priorityTimeout = (Uint2) value.intvalue;
  1402.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1403.             goto ServiceFail;
  1404.     }
  1405.  
  1406.     if (atp == SVC_ENTRY_priority_penalty) {
  1407.         if (AsnReadVal(aip, atp, &value) < 0)
  1408.             goto ServiceFail;
  1409.         svcptr->priorityPenalty = (Uint2) value.intvalue;
  1410.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1411.             goto ServiceFail;
  1412.     }
  1413.  
  1414.     if (atp == NULL)
  1415.         goto ServiceFail;
  1416.  
  1417.     if (AsnReadVal(aip, atp, &value) < 0)
  1418.         goto ServiceFail;
  1419.     return 0;
  1420.  
  1421.   ServiceFail:
  1422.     return -1;
  1423. } /* readService */
  1424.  
  1425.  
  1426. static void 
  1427. writeService(NISvcPtr svcptr)
  1428. {
  1429.     DataVal     value;
  1430.     NodePtr     np;
  1431.     NodePtr     lastnode;
  1432.  
  1433.     value.ptrvalue = (Pointer) svcptr->name;
  1434.     AsnWrite(aip, SVC_ENTRY_name, &value);
  1435.     value.intvalue = (Int4) svcptr->minVersion;
  1436.     AsnWrite(aip, SVC_ENTRY_minvers, &value);
  1437.     value.intvalue = (Int4) svcptr->maxVersion;
  1438.     AsnWrite(aip, SVC_ENTRY_maxvers, &value);
  1439.     
  1440.     if (svcptr->id != 0) {
  1441.         value.intvalue = (Int4) svcptr->id;
  1442.         AsnWrite(aip, SVC_ENTRY_id, &value);
  1443.     }
  1444.     if (svcptr->priority != 0) {
  1445.         value.intvalue = (Int4) svcptr->priority;
  1446.         AsnWrite(aip, SVC_ENTRY_priority, &value);
  1447.     }
  1448.     if (svcptr->group != NULL) {
  1449.         value.ptrvalue = (Pointer) svcptr->group;
  1450.         AsnWrite(aip, SVC_ENTRY_group, &value);
  1451.     }
  1452.     if (svcptr->descrip != NULL) {
  1453.         value.ptrvalue = (Pointer) svcptr->descrip;
  1454.         AsnWrite(aip, SVC_ENTRY_description, &value);
  1455.     }
  1456.  
  1457.     np = svcptr->typeL;
  1458.     if (np != NULL) {
  1459.         AsnStartStruct(aip, SVC_ENTRY_types);
  1460.         lastnode = np->last;
  1461.         while (np != NULL) {
  1462.             value.ptrvalue = (Pointer) np->elem;
  1463.             AsnWrite(aip, SVC_ENTRY_types_E, &value);
  1464.             if (np == lastnode)
  1465.                 break;
  1466.             np = np->next;
  1467.         }
  1468.         AsnEndStruct(aip, SVC_ENTRY_types);
  1469.     }
  1470.  
  1471.     if (svcptr->priorityTimeout != 0)
  1472.     {
  1473.         value.intvalue = svcptr->priorityTimeout;
  1474.         AsnWrite(aip, SVC_ENTRY_priority_timeout, &value);
  1475.     }
  1476.  
  1477.     if (svcptr->priorityPenalty != 0)
  1478.     {
  1479.         value.intvalue = svcptr->priorityPenalty;
  1480.         AsnWrite(aip, SVC_ENTRY_priority_penalty, &value);
  1481.     }
  1482. } /* writeService */
  1483.  
  1484.  
  1485. /************************************ RESOURCE ********************************/
  1486.  
  1487. NIResPtr 
  1488. NI_MakeResource(void)
  1489. {
  1490.     NIResPtr    rp;
  1491.     
  1492.     rp = (NIResPtr) MemNew(sizeof(NIResource));
  1493.     rp->name = NULL;
  1494.     rp->type = NULL;
  1495.     rp->minVersion = 0;
  1496.     rp->maxVersion = 0;
  1497.     rp->id = 0;
  1498.     rp->group = NULL;
  1499.     rp->descrip = NULL;
  1500.     return rp;
  1501. } /* NI_MakeResource() */
  1502.  
  1503.  
  1504. Int2 
  1505. NI_DestroyResource(NIResPtr rp)
  1506. {
  1507.     if (rp == NULL)
  1508.         return 1;
  1509.     if (rp->name != NULL)
  1510.         MemFree(rp->name);
  1511.     if (rp->type != NULL)
  1512.         MemFree(rp->type);
  1513.     if (rp->group != NULL)
  1514.         MemFree(rp->group);
  1515.     if (rp->descrip != NULL)
  1516.         MemFree(rp->descrip);
  1517.     MemFree(rp);
  1518.     return 0;
  1519. } /* NI_DestroyResource */
  1520.  
  1521.  
  1522. static int
  1523. readResource(NIResPtr resptr)
  1524. {
  1525.     DataVal     value;
  1526.  
  1527.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_name */
  1528.         goto ResourceFail;
  1529.     if (AsnReadVal(aip, atp, &value) < 0)
  1530.         goto ResourceFail;
  1531.     resptr->name = (CharPtr) value.ptrvalue;
  1532.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_type */
  1533.         goto ResourceFail;
  1534.     if (AsnReadVal(aip, atp, &value) < 0)
  1535.         goto ResourceFail;
  1536.     resptr->type = (CharPtr) value.ptrvalue;
  1537.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_minvers */
  1538.         goto ResourceFail;
  1539.     if (AsnReadVal(aip, atp, &value) < 0)
  1540.         goto ResourceFail;
  1541.     resptr->minVersion = (Uint2) value.intvalue;
  1542.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_maxvers */
  1543.         goto ResourceFail;
  1544.     if (AsnReadVal(aip, atp, &value) < 0)
  1545.         goto ResourceFail;
  1546.     resptr->maxVersion = (Uint2) value.intvalue;
  1547.     
  1548.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1549.         goto ResourceFail;
  1550.     if (atp == RES_ENTRY_id) {                          /* RES_ENTRY_id */
  1551.         if (AsnReadVal(aip, atp, &value) < 0)
  1552.             goto ResourceFail;
  1553.         resptr->id = (Uint2) value.intvalue;
  1554.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1555.             goto ResourceFail;
  1556.     }
  1557.     if (atp == RES_ENTRY_group) {                       /* RES_ENTRY_group */
  1558.         if (AsnReadVal(aip, atp, &value) < 0)
  1559.             goto ResourceFail;
  1560.         resptr->group = (CharPtr) value.ptrvalue;
  1561.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1562.             goto ResourceFail;
  1563.     }
  1564.     if (atp == RES_ENTRY_description) {                 /* RES_ENTRY_description */
  1565.         if (AsnReadVal(aip, atp, &value) < 0)
  1566.             goto ResourceFail;
  1567.         resptr->descrip = (CharPtr) value.ptrvalue;
  1568.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1569.             goto ResourceFail;
  1570.     }
  1571.     if (AsnReadVal(aip, atp, &value) < 0)
  1572.         goto ResourceFail;
  1573.     return 0;
  1574.  
  1575.   ResourceFail:
  1576.     return -1;
  1577. } /* readResource */
  1578.  
  1579.  
  1580. static void 
  1581. writeResource(NIResPtr resptr)
  1582. {
  1583.     DataVal     value;
  1584.  
  1585.     value.ptrvalue = (Pointer) resptr->name;
  1586.     AsnWrite(aip, RES_ENTRY_name, &value);
  1587.     value.ptrvalue = (Pointer) resptr->type;
  1588.     AsnWrite(aip, RES_ENTRY_type, &value);
  1589.     value.intvalue = (Int4) resptr->minVersion;
  1590.     AsnWrite(aip, RES_ENTRY_minvers, &value);
  1591.     value.intvalue = (Int4) resptr->maxVersion;
  1592.     AsnWrite(aip, RES_ENTRY_maxvers, &value);
  1593.     
  1594.     if (resptr->id != 0) {
  1595.         value.intvalue = (Int4) resptr->id;
  1596.         AsnWrite(aip, RES_ENTRY_id, &value);
  1597.     }
  1598.     if (resptr->group != NULL) {
  1599.         value.ptrvalue = (Pointer) resptr->group;
  1600.         AsnWrite(aip, RES_ENTRY_group, &value);
  1601.     }
  1602.     if (resptr->descrip != NULL) {
  1603.         value.ptrvalue = (Pointer) resptr->descrip;
  1604.         AsnWrite(aip, RES_ENTRY_description, &value);
  1605.     }
  1606. } /* writeResource */
  1607.  
  1608.  
  1609. /************************************ REGION *********************************/
  1610.  
  1611. NIRegionPtr 
  1612. NI_MakeRegion(void)
  1613. {
  1614.     NIRegionPtr    rp;
  1615.     
  1616.     rp = (NIRegionPtr) MemNew(sizeof(NIRegion));
  1617.     rp->regionName = NULL;
  1618.     rp->priorityDelta = 0;
  1619.     return rp;
  1620. } /* NI_MakeRegion() */
  1621.  
  1622.  
  1623. Int2 
  1624. NI_DestroyRegion(NIRegionPtr rp)
  1625. {
  1626.     if (rp == NULL)
  1627.         return 1;
  1628.     if (rp->regionName != NULL)
  1629.         MemFree(rp->regionName);
  1630.  
  1631.     MemFree(rp);
  1632.     return 0;
  1633. } /* NI_DestroyRegion() */
  1634.  
  1635.  
  1636. static int 
  1637. readRegion(NIRegionPtr regptr)
  1638. {
  1639.     DataVal     value;
  1640.  
  1641.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* REGION_DESCR_region_name */
  1642.         goto RegionFail;
  1643.     if (AsnReadVal(aip, atp, &value) < 0)
  1644.         goto RegionFail;
  1645.     regptr->regionName = (CharPtr) value.ptrvalue;
  1646.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* REGION_DESCR_priority_delta */
  1647.         goto RegionFail;
  1648.     if (AsnReadVal(aip, atp, &value) < 0)
  1649.         goto RegionFail;
  1650.     regptr->priorityDelta = (Uint2) value.intvalue;
  1651.  
  1652.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1653.         goto RegionFail;
  1654.  
  1655.     if (AsnReadVal(aip, atp, &value) < 0)
  1656.         goto RegionFail;
  1657.     return 0;
  1658.  
  1659.   RegionFail:
  1660.     return -1;
  1661. } /* readRegion */
  1662.  
  1663.  
  1664. static void 
  1665. writeRegion(NIRegionPtr regptr)
  1666. {
  1667.     DataVal     value;
  1668.  
  1669.     value.ptrvalue = (Pointer) regptr->regionName;
  1670.     AsnWrite(aip, REGION_DESCR_region_name, &value);
  1671.     value.intvalue = (Int4) regptr->priorityDelta;
  1672.     AsnWrite(aip, REGION_DESCR_priority_delta, &value);
  1673. } /* writeRegion */
  1674.  
  1675.  
  1676.  
  1677. /************************************ DispInfo ********************************/
  1678.  
  1679. NIDispInfoPtr 
  1680. NI_MakeDispInfo(void)
  1681. {
  1682.     NIDispInfoPtr   dip;
  1683.     
  1684.     dip = (NIDispInfoPtr) MemNew(sizeof(NIDispInfo));
  1685.     dip->serialno = -1;
  1686.     dip->isalternatelist = FALSE;
  1687.     dip->numdispatchers = 0;
  1688.     dip->displist = NULL;
  1689.     return dip;
  1690. } /* NI_MakeDispInfo */
  1691.  
  1692.  
  1693. Int2 
  1694. NI_DestroyDispInfo(NIDispInfoPtr dip)
  1695. {
  1696.     Int2 num;
  1697.  
  1698.     if (dip == NULL)
  1699.         return 1;
  1700.     if (dip->displist != NULL)
  1701.     {
  1702.         for (num = 0; num < dip->numdispatchers; num++)
  1703.         {
  1704.             dip->displist[num] = (CharPtr) MemFree(dip->displist[num]);
  1705.         }
  1706.         MemFree(dip->displist);
  1707.     }
  1708.     MemFree(dip);
  1709.     return 0;
  1710. } /* NI_DestroyDispInfo */
  1711.  
  1712.  
  1713. static int 
  1714. readDispInfo(NIDispInfoPtr dip)
  1715. {
  1716.     DataVal     value;
  1717.     int         num;
  1718.  
  1719.     if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != DISPATCHER_INFO_serial_no)
  1720.         goto DispInfoFail;
  1721.     if (AsnReadVal(aip, atp, &value) < 0)
  1722.         goto DispInfoFail;
  1723.     dip->serialno = value.intvalue;
  1724.     
  1725.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* is altlist?*/
  1726.         goto DispInfoFail;
  1727.     if (atp == INFO_is_alternate_list) {
  1728.         if (AsnReadVal(aip, atp, &value) < 0)
  1729.             goto DispInfoFail;
  1730.         dip->isalternatelist = value.boolvalue;
  1731.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)           /* num disps ?*/
  1732.             goto DispInfoFail;
  1733.     }
  1734.     
  1735.     if (atp == DISPATCHER_INFO_num_dispatchers) {
  1736.         if (AsnReadVal(aip, atp, &value) < 0)
  1737.             goto DispInfoFail;
  1738.         dip->numdispatchers = (int) value.intvalue;
  1739.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)           /* disps ? */
  1740.             goto DispInfoFail;
  1741.     }
  1742.     if (atp == DISPATCHER_INFO_disp_list) {
  1743.         if (AsnReadVal(aip, atp, &value) < 0)
  1744.             goto DispInfoFail;
  1745.         dip->displist = (CharPtr PNTR) MemNew(sizeof(CharPtr) * dip->numdispatchers);
  1746.         atp = AsnReadId(aip, amp, atp);
  1747.         for (num = 0; num < dip->numdispatchers &&
  1748.              atp == DISPATCHER_INFO_disp_list_E; num++)
  1749.         {
  1750.             if (AsnReadVal(aip, atp, &value) <= 0)
  1751.                 goto DispInfoFail;
  1752.             dip->displist[num] = (CharPtr) value.ptrvalue;
  1753.             atp = AsnReadId(aip, amp, atp);
  1754.         }
  1755.         if (AsnReadVal(aip, atp, &value) <= 0)
  1756.             goto DispInfoFail;
  1757.         atp = AsnReadId(aip, amp, atp);
  1758.     }
  1759.     if (AsnReadVal(aip, atp, &value) < 0)
  1760.         goto DispInfoFail;
  1761.     return 0;
  1762.  
  1763.   DispInfoFail:
  1764.     return -1;
  1765. } /* readDispInfo */
  1766.  
  1767.  
  1768. static void 
  1769. writeDispInfo(NIDispInfoPtr dip)
  1770. {
  1771.     DataVal     value;
  1772.     int         num;
  1773.     
  1774.     if (dip == NULL)
  1775.         return;
  1776.     value.intvalue = dip->serialno;
  1777.     AsnWrite(aip, DISPATCHER_INFO_serial_no, &value);
  1778.     value.boolvalue = dip->isalternatelist;
  1779.     AsnWrite(aip, INFO_is_alternate_list, &value);
  1780.     value.intvalue = dip->numdispatchers;
  1781.     AsnWrite(aip, DISPATCHER_INFO_num_dispatchers, &value);
  1782.     if (dip->displist != NULL) {
  1783.         AsnStartStruct (aip, DISPATCHER_INFO_disp_list);
  1784.         for (num = 0; num < dip->numdispatchers; num++) {
  1785.             value.ptrvalue = dip->displist[num];
  1786.             AsnWrite (aip, DISPATCHER_INFO_disp_list_E, &value);
  1787.         }
  1788.         AsnEndStruct (aip, DISPATCHER_INFO_disp_list);
  1789.     }
  1790. } /* writeDispInfo */
  1791.  
  1792. int 
  1793. NI_ReadDispInfo(AsnIoPtr extaip, AsnTypePtr extatp, NIDispInfoPtr dip)
  1794. {
  1795.     AsnIoPtr     savaip = aip;
  1796.     AsnTypePtr   savatp = atp;
  1797.     DataVal      value;
  1798.     int          retval = -1;
  1799.  
  1800.     aip = extaip;
  1801.     atp = extatp;
  1802.     if ((atp = AsnReadId(aip, amp, atp)) == DISPATCHER_INFO)
  1803.     {
  1804.         if (AsnReadVal(aip, atp, &value) >= 0)
  1805.         {
  1806.             retval = readDispInfo(dip);
  1807.         }
  1808.     }
  1809.     aip = savaip;
  1810.     atp = savatp;
  1811.     return retval;
  1812. }
  1813.  
  1814. void
  1815. NI_WriteDispInfo(AsnIoPtr extaip, AsnTypePtr extatp, NIDispInfoPtr dip)
  1816. {
  1817.     AsnIoPtr savaip = aip;
  1818.     AsnTypePtr savatp = atp;
  1819.  
  1820.     aip = extaip;
  1821.     atp = extatp;
  1822.     writeDispInfo(dip);
  1823.     aip = savaip;
  1824.     atp = savatp;
  1825. }
  1826.  
  1827.  
  1828. /************************************ TOOLSET *********************************/
  1829.  
  1830. NIToolsetPtr 
  1831. NI_MakeToolset(void)
  1832. {
  1833.     NIToolsetPtr        tsp;
  1834.     
  1835.     tsp = (NIToolsetPtr) MemNew(sizeof(NIToolset));
  1836.     tsp->host = NULL;
  1837.     tsp->motd = NULL;
  1838.     tsp->services = NULL;
  1839.     tsp->resources = NULL;
  1840.     tsp->regions = NULL;
  1841.     return tsp;
  1842. } /* NI_MakeToolset */
  1843.  
  1844.  
  1845. Int2 
  1846. NI_DestroyToolset(NIToolsetPtr tsp)
  1847. {
  1848.     NodePtr             np;
  1849.     
  1850.     if (tsp == NULL)
  1851.         return 1;
  1852.     if (tsp->host != NULL)
  1853.         MemFree(tsp->host);
  1854.     if (tsp->motd != NULL)
  1855.         MemFree(tsp->motd);
  1856.     
  1857.     if ((np = tsp->services) != NULL) {
  1858.         do {
  1859.             NI_DestroyService((NISvcPtr)np->elem);
  1860.             np = ListDelete(np);
  1861.         } while (np != NULL);
  1862.     }   
  1863.     
  1864.     if ((np = tsp->resources) != NULL) {
  1865.         do {
  1866.             NI_DestroyResource((NIResPtr)np->elem);
  1867.             np = ListDelete(np);
  1868.         } while (np != NULL);
  1869.     }   
  1870.     
  1871.     if ((np = tsp->regions) != NULL) {
  1872.         do {
  1873.             NI_DestroyRegion((NIRegionPtr)np->elem);
  1874.             np = ListDelete(np);
  1875.         } while (np != NULL);
  1876.     }   
  1877.     
  1878.     MemFree(tsp);
  1879.     return 0;
  1880. } /* NI_DestroyToolset */
  1881.  
  1882.  
  1883. NIToolsetPtr 
  1884. NI_GetCatToolset(NIToolsetPtr tsp)
  1885. {
  1886.     NIToolsetPtr        dtsp;
  1887.     NISvcPtr            svcp, tsvcp;
  1888.     NIResPtr            resp, tresp;
  1889.     NodePtr             np;
  1890.     
  1891.     dtsp = NI_MakeToolset();
  1892.     
  1893.     if (tsp->host != NULL)
  1894.         dtsp->host = StringSave(tsp->host);
  1895.     if (tsp->motd != NULL)
  1896.         dtsp->motd = StringSave(tsp->motd);
  1897.     
  1898.     if (tsp->services != NULL) {
  1899.         np = tsp->services->last;
  1900.         do {
  1901.             np = ListGetNext(np);
  1902.             svcp = (NISvcPtr) np->elem;
  1903.             /* note that services which are a "subset" of another listed */
  1904.             /* service are filtered-out here                             */
  1905.             if (svcp != NULL && svcp->subSetList == NULL) {
  1906.                 tsvcp = NI_MakeService();
  1907.                 if (svcp->name != NULL)
  1908.                     tsvcp->name = StringSave(svcp->name);
  1909.  
  1910.                 if (svcp->typeL != NULL)
  1911.                 { /* make a copy of the list */
  1912.                     tsvcp->typeL = ListStrCopy(svcp->typeL);
  1913.                 }
  1914.  
  1915.                 tsvcp->minVersion = svcp->minVersion;
  1916.                 tsvcp->maxVersion = svcp->maxVersion;
  1917.                 tsvcp->id = 0;          /* these three not sent in catalog */
  1918.                 tsvcp->priority = 0;
  1919.                 tsvcp->group = NULL;
  1920.                 if (svcp->descrip != NULL)
  1921.                     tsvcp->descrip = StringSave(svcp->descrip);
  1922.                 dtsp->services = ListInsert((VoidPtr) tsvcp, dtsp->services);
  1923.             }
  1924.         } while (np != tsp->services->last);
  1925.         if (dtsp->services != NULL)
  1926.         {
  1927.             dtsp->services = dtsp->services->next;  /* point to first */
  1928.         }
  1929.     }
  1930.     
  1931.     if (tsp->resources != NULL) {
  1932.         np = tsp->resources->last;
  1933.         do {
  1934.             np = ListGetNext(np);
  1935.             resp = (NIResPtr) np->elem;
  1936.             if (resp != NULL) {
  1937.                 tresp = NI_MakeResource();
  1938.                 if (resp->name != NULL)
  1939.                     tresp->name = StringSave(resp->name);
  1940.                 if (resp->type != NULL)
  1941.                     tresp->type = StringSave(resp->type);
  1942.                 tresp->minVersion = resp->minVersion;
  1943.                 tresp->maxVersion = resp->maxVersion;
  1944.                 tresp->id = 0;          /* these two not sent in catalog */
  1945.                 tresp->group = NULL;
  1946.                 if (resp->descrip != NULL)
  1947.                     tresp->descrip = StringSave(resp->descrip);
  1948.                 dtsp->resources = ListInsert((VoidPtr) tresp, dtsp->resources);
  1949.             }
  1950.         } while (np != tsp->resources->last);
  1951.         if (dtsp->resources != NULL)
  1952.         {
  1953.             dtsp->resources = dtsp->resources->next;        /* point to first */
  1954.         }
  1955.     }
  1956.     
  1957.     return dtsp;
  1958. } /* NI_GetCatToolset */
  1959.  
  1960.  
  1961. static int
  1962. readToolset(NIToolsetPtr tsp)
  1963. {
  1964.     DataVal     value;
  1965.     NISvcPtr    svcp;
  1966.     NIResPtr    resp;
  1967.     NIRegionPtr reg;
  1968.     
  1969.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* TOOLSET_host */
  1970.         goto ToolsetFail;
  1971.     if (AsnReadVal(aip, atp, &value) < 0)
  1972.         goto ToolsetFail;
  1973.     tsp->host = (CharPtr) value.ptrvalue;
  1974.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1975.         goto ToolsetFail;
  1976.     
  1977.     if (atp == TOOLSET_motd) {                  /* TOOLSET_motd ? */
  1978.         if (AsnReadVal(aip, atp, &value) < 0)
  1979.             goto ToolsetFail;
  1980.         tsp->motd = (CharPtr) value.ptrvalue;
  1981.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1982.             goto ToolsetFail;
  1983.     }
  1984.     if (atp == TOOLSET_services) {
  1985.         if (AsnReadVal(aip, atp, &value) < 0)
  1986.             goto ToolsetFail;
  1987.         while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_services_E) {
  1988.             if (AsnReadVal(aip, atp, &value) < 0)
  1989.                 goto ToolsetFail;
  1990.             svcp = NI_MakeService();
  1991.             readService(svcp);
  1992.             tsp->services = ListInsert((VoidPtr) svcp, tsp->services);
  1993.         }
  1994.         if (atp == NULL)
  1995.             goto ToolsetFail;
  1996.         tsp->services = tsp->services->next;    /* point to first */
  1997.         if (AsnReadVal(aip, atp, &value) < 0)
  1998.             goto ToolsetFail;
  1999.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2000.             goto ToolsetFail;
  2001.     }
  2002.     if (atp == TOOLSET_resources) {
  2003.         if (AsnReadVal(aip, atp, &value) < 0)
  2004.             goto ToolsetFail;
  2005.         while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_resources_E) {
  2006.             if (AsnReadVal(aip, atp, &value) < 0)
  2007.                 goto ToolsetFail;
  2008.             resp = NI_MakeResource();
  2009.             readResource(resp);
  2010.             tsp->resources = ListInsert((VoidPtr) resp, tsp->resources);
  2011.         }
  2012.         if (atp == NULL)
  2013.             goto ToolsetFail;
  2014.         tsp->resources = tsp->resources->next;  /* point to first */
  2015.         if (AsnReadVal(aip, atp, &value) < 0)
  2016.             goto ToolsetFail;
  2017.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2018.             goto ToolsetFail;
  2019.     }
  2020.     if (atp == TOOLSET_regions) {
  2021.         if (AsnReadVal(aip, atp, &value) < 0)
  2022.             goto ToolsetFail;
  2023.         while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_regions_E) {
  2024.             if (AsnReadVal(aip, atp, &value) < 0)
  2025.                 goto ToolsetFail;
  2026.             reg = NI_MakeRegion();
  2027.             readRegion(reg);
  2028.             tsp->regions = ListInsert((VoidPtr) reg, tsp->regions);
  2029.         }
  2030.         if (atp == NULL)
  2031.             goto ToolsetFail;
  2032.         tsp->regions = tsp->regions->next;  /* point to first */
  2033.         if (AsnReadVal(aip, atp, &value) < 0)
  2034.             goto ToolsetFail;
  2035.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2036.             goto ToolsetFail;
  2037.     }
  2038.  
  2039.     if (AsnReadVal(aip, atp, &value) < 0)
  2040.         goto ToolsetFail;
  2041.     return 0;
  2042.  
  2043.   ToolsetFail:
  2044.     return -1;
  2045. } /* readToolset */
  2046.  
  2047. static void 
  2048. writeToolset(NIToolsetPtr tsp)
  2049. {
  2050.     DataVal     value;
  2051.     NodePtr     np, lastnode;
  2052.     
  2053.     if (tsp->host != NULL)
  2054.         value.ptrvalue = (Pointer) tsp->host;
  2055.     else
  2056.         value.ptrvalue = (Pointer) StringSave("N/A");
  2057.     AsnWrite(aip, TOOLSET_host, &value);
  2058.     
  2059.     if (tsp->motd != NULL) {
  2060.         value.ptrvalue = (Pointer) tsp->motd;
  2061.         AsnWrite(aip, TOOLSET_motd, &value);
  2062.     }
  2063.     np = tsp->services;
  2064.     if (np != NULL) {
  2065.         AsnStartStruct(aip, TOOLSET_services);
  2066.         lastnode = np->last;
  2067.         while (np != NULL) {
  2068.             AsnStartStruct(aip, TOOLSET_services_E);
  2069.             writeService((NISvcPtr) np->elem);
  2070.             AsnEndStruct(aip, TOOLSET_services_E);
  2071.             if (np == lastnode)
  2072.                 break;
  2073.             np = np->next;
  2074.         }
  2075.         AsnEndStruct(aip, TOOLSET_services);
  2076.     }
  2077.     np = tsp->resources;
  2078.     if (np != NULL) {
  2079.         AsnStartStruct(aip, TOOLSET_resources);
  2080.         lastnode = np->last;
  2081.         while (np != NULL) {
  2082.             AsnStartStruct(aip, TOOLSET_resources_E);
  2083.             writeResource((NIResPtr) np->elem);
  2084.             AsnEndStruct(aip, TOOLSET_resources_E);
  2085.             if (np == lastnode)
  2086.                 break;
  2087.             np = np->next;
  2088.         }
  2089.         AsnEndStruct(aip, TOOLSET_resources);
  2090.     }
  2091.     np = tsp->regions;
  2092.     if (np != NULL) {
  2093.         AsnStartStruct(aip, TOOLSET_regions);
  2094.         lastnode = np->last;
  2095.         while (np != NULL) {
  2096.             AsnStartStruct(aip, TOOLSET_regions_E);
  2097.             writeRegion((NIRegionPtr) np->elem);
  2098.             AsnEndStruct(aip, TOOLSET_regions_E);
  2099.             if (np == lastnode)
  2100.                 break;
  2101.             np = np->next;
  2102.         }
  2103.         AsnEndStruct(aip, TOOLSET_regions);
  2104.     }
  2105. } /* writeToolset */
  2106.  
  2107.  
  2108. /******************************************************************************/
  2109. /*                                                                            */
  2110. /*      Message and Handle Functions                                          */
  2111. /*                                                                            */
  2112. /******************************************************************************/
  2113.  
  2114. /*
  2115.  * Purpose:     "High level" message read for ASN.1 messages
  2116.  *
  2117.  * Parameters:
  2118.  *   hp           "Message handle", describing parameters of input environment
  2119.  *   unblocked    Flag indicating whether input should "block" if unable
  2120.  *                to read a complete message
  2121.  *
  2122.  * Returns:
  2123.  *                NULL, if unable to read a message ... if hp->have_blocked is
  2124.  *                  set, then this reflects an inability to read a complete
  2125.  *                  message at this time
  2126.  *                a pointer to the message which was just read, otherwise
  2127.  *
  2128.  *
  2129.  * Description:
  2130.  *              Try to read a message from the socket specified by the hp
  2131.  *              data structure. A message must begin with the "MESSAGE" 
  2132.  *              identifier, followed by the type of the message. Once the
  2133.  *              type of the message has been determined, the remainder of
  2134.  *              the message is read using the corresponding readXXX()
  2135.  *              function.
  2136.  *
  2137.  *              Matters are more complex when the "unblocked" parameter
  2138.  *              is TRUE. In this case, if a failure occurs on a message read,
  2139.  *              an attempt is made to see whether any bytes of data were
  2140.  *              read from the socket upon this invocation. If so, the
  2141.  *              have_blocked flag is set for the caller, and AsnIoReset() is
  2142.  *              called to deal with a future attempt to read from this socket
  2143.  *              when more data becomes available.
  2144.  *
  2145.  * Note:
  2146.  *              This is the highest level read function which should be
  2147.  *              called by an application program. All the other "static"
  2148.  *              functions called here should not be called directly by an
  2149.  *              application program.
  2150.  *
  2151.  *              The ASN.1 error handling is performing using the setjmp()/
  2152.  *              longjmp() paradigm, where a function can return to an earlier
  2153.  *              context if an error occurs.
  2154.  *
  2155.  *              Currently, it is not possible to distinguish
  2156.  *              between an ASN.1 format error, and an ASN failure due to
  2157.  *              inability to read the requested quantity of data. For this
  2158.  *              reason, if the "unblocked" option is selected, it will take
  2159.  *              hp->r_timeout seconds to detect either of these
  2160.  *              conditions. In the best of all possible worlds, it would
  2161.  *              be possible to distinguish between "data not YET available"
  2162.  *              and "invalid data" conditions.
  2163.  */
  2164.  
  2165. NIMsgPtr 
  2166. MsgRead(MHandPtr hp, Boolean unblocked)
  2167. {
  2168.     DataVal     value;
  2169.     NIMsgPtr    mp = NULL;
  2170.     int         start_byte_count = hp->num_queued_bytes;
  2171.     NodePtr     timer = NULL;
  2172.  
  2173.     ni_errno = NIE_MSGREAD;
  2174.  
  2175.     hp->unblocked_mode = unblocked;
  2176.     hp->have_blocked = FALSE;
  2177.  
  2178.     /* for unblocked I/O, set a "hangup" timeout which can be detected at    */
  2179.     /* at later time, if we are unable to read a complete or valid message   */
  2180.     if (unblocked && hp->readTimeoutHook != NULL)
  2181.         timer = NI_SetTimer(time(NULL) + hp->r_timeout, hp->readTimeoutHook,
  2182.                             (VoidPtr) hp);
  2183.     hp->readTimer = timer;
  2184.         
  2185.     if (hp->longjump == TRUE) {
  2186.         if (SetJump(ni_env)) {
  2187.             /* return from LongJump (error handler) */
  2188.             goto MsgReadFail;
  2189.         }
  2190.     }
  2191.  
  2192.     StringCpy(ni_errtext, "AsnReadId or AsnReadVal returned bad value");
  2193.     aip = hp->raip;
  2194.     atp = MESSAGE;
  2195.     if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE)    /* Must read a MESSAGE */
  2196.         goto MsgReadFail;       /* don't have to read val as Null return is always fatal to channel */
  2197.     if (AsnReadVal(aip, atp, &value) < 0)
  2198.         goto MsgReadFail;
  2199.     
  2200.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* type of message */
  2201.         goto MsgReadFail;
  2202.     if (AsnReadVal(aip, atp, &value) < 0)
  2203.         goto MsgReadFail;
  2204.     
  2205.     mp = (NIMsgPtr) MemNew(sizeof(NIMessage));
  2206.     mp->conid = hp->conid;
  2207.     mp->type = NI_UNKNOWN;
  2208.     
  2209.     if (atp == MESSAGE_ack) {
  2210.         if ((mp->msun.ack = readACK()) != NULL)
  2211.             mp->type = NI_ACK;
  2212.         goto gotmessage;
  2213.     }
  2214.     
  2215.     if (atp == MESSAGE_nack) {
  2216.         if ((mp->msun.nack = readNACK()) != NULL)
  2217.             mp->type = NI_NACK;
  2218.         goto gotmessage;
  2219.     }
  2220.     
  2221.     if (atp == MESSAGE_login) {
  2222.         if ((mp->msun.login = readLOGIN()) != NULL)
  2223.             mp->type = NI_LOGIN;
  2224.         goto gotmessage;
  2225.     }
  2226.     
  2227.     if (atp == MESSAGE_svc_list) {
  2228.         if ((mp->msun.svclist = readSVC_LIST()) != NULL)
  2229.             mp->type = NI_SVC_LIST;
  2230.         goto gotmessage;
  2231.     }
  2232.     
  2233.     if (atp == MESSAGE_svc_request) {
  2234.         if ((mp->msun.svcreq = readSVC_REQUEST()) != NULL)
  2235.             mp->type = NI_SVC_REQUEST;
  2236.         goto gotmessage;
  2237.     }
  2238.     
  2239.     if (atp == MESSAGE_svc_response) {
  2240.         if ((mp->msun.svcresp = readSVC_RESPONSE()) != NULL)
  2241.             mp->type = NI_SVC_RESPONSE;
  2242.         goto gotmessage;
  2243.     }
  2244.     
  2245.     if (atp == MESSAGE_command) {
  2246.         if ((mp->msun.command = readCOMMAND()) != NULL)
  2247.             mp->type = NI_COMMAND;
  2248.         goto gotmessage;
  2249.     }
  2250.     
  2251.     if (atp == MESSAGE_acct) {
  2252.         if ((mp->msun.acct = readACCT()) != NULL)
  2253.             mp->type = NI_ACCT;
  2254.         goto gotmessage;
  2255.     }
  2256.     
  2257.     if (atp == MESSAGE_catalog) {
  2258.         if ((mp->msun.catalog = readCATALOG()) != NULL)
  2259.             mp->type = NI_CATALOG;
  2260.         goto gotmessage;
  2261.     }
  2262.     
  2263.   gotmessage:
  2264.     if (mp->type == NI_UNKNOWN) {
  2265.         StringCpy(ni_errtext, "unknown msg type");
  2266.         goto MsgReadFail;
  2267.     }
  2268.     else { /* got good stuff */
  2269.         MsgFreeSavedData(hp); /* free associated data */
  2270.         hp->unblocked_mode = FALSE;
  2271.         hp->have_blocked = FALSE;
  2272.         NI_CancelTimer (hp->readTimer);
  2273.         hp->readTimer = NULL;
  2274.         return mp;
  2275.     }
  2276.     
  2277.   MsgReadFail:
  2278.     if (mp != NULL)
  2279.         MsgDestroy(mp);
  2280.  
  2281.     /* if ( things didn't go well, but there was more data read from the     */
  2282.     /*      socket ) then                                                    */
  2283.     if (start_byte_count < hp->num_queued_bytes)
  2284.         hp->have_blocked = TRUE; /* set things up to try again */
  2285.  
  2286.     if (hp->have_blocked)
  2287.     { /* failed due to data unavailability */
  2288.         hp->cur_index = 0; /* reset queued read pointer */
  2289.         AsnIoReset (aip);  /* reset ASN input stream */
  2290.         /* caller should try again later, based upon detecting hp->have_blocked */
  2291.     }
  2292.     hp->unblocked_mode = FALSE;
  2293.     return NULL;
  2294. } /* MsgRead */
  2295.  
  2296.  
  2297.  
  2298. /*
  2299.  * Purpose:     "High level" message write for ASN.1 messages
  2300.  *
  2301.  * Parameters:
  2302.  *   hp           "Message handle", describing parameters of I/O environment
  2303.  *   mp           Message to be written
  2304.  *
  2305.  * Returns:
  2306.  *                -1, if unable to write the message
  2307.  *                0, otherwise
  2308.  *
  2309.  *
  2310.  * Description:
  2311.  *              Try to write a message from the socket specified by the hp
  2312.  *              data structure. The writing of the message is performed
  2313.  *              using the writeXXX() function which corresponds to the type
  2314.  *              of the message to be written.
  2315.  */
  2316.  
  2317. Int2 
  2318. MsgWrite(MHandPtr hp, NIMsgPtr mp)
  2319. {
  2320.     DataVal     value;
  2321.  
  2322.     ni_errno = NIE_MSGWRITE;
  2323.  
  2324.     if (hp->longjump == TRUE) {
  2325.         if (SetJump(ni_env)) {
  2326.             /* return from LongJump (error handler) */
  2327.             MsgDestroy(mp);             /* failing, so destroy it */    
  2328.             return -1;
  2329.         }
  2330.     }
  2331.     
  2332.     aip = hp->waip;
  2333.     AsnWrite(aip, MESSAGE, &value);
  2334.     
  2335.     switch (mp->type) {
  2336.       case NI_ACK:
  2337.         writeACK(mp->msun.ack);
  2338.         break;
  2339.         
  2340.       case NI_NACK:
  2341.         writeNACK(mp->msun.nack);
  2342.         break;
  2343.         
  2344.       case NI_LOGIN:
  2345.         writeLOGIN(mp->msun.login);
  2346.         break;
  2347.         
  2348.       case NI_SVC_LIST:
  2349.         writeSVC_LIST(mp->msun.svclist);
  2350.         break;
  2351.         
  2352.       case NI_SVC_REQUEST:
  2353.         writeSVC_REQUEST(mp->msun.svcreq);
  2354.         break;
  2355.         
  2356.       case NI_SVC_RESPONSE:
  2357.         writeSVC_RESPONSE(mp->msun.svcresp);
  2358.         break;
  2359.         
  2360.       case NI_COMMAND:
  2361.         writeCOMMAND(mp->msun.command);
  2362.         break;
  2363.         
  2364.       case NI_ACCT:
  2365.         writeACCT(mp->msun.acct);
  2366.         break;
  2367.         
  2368.       case NI_CATALOG:
  2369.         writeCATALOG(mp->msun.catalog);
  2370.         break;
  2371.         
  2372.       default:
  2373.         ni_errno = NIE_MSGUNK;
  2374.         StringCpy(ni_errtext, "unable to write msg");
  2375.         MsgDestroy(mp);
  2376.         return -1;
  2377.     }
  2378.     
  2379.     AsnIoFlush(aip);
  2380.     MsgDestroy(mp);
  2381.     return 0;
  2382. } /* MsgWrite */
  2383.  
  2384.  
  2385.  
  2386. /*
  2387.  * Purpose:     Build a message of the specified type, populating it with
  2388.  *              a pointer to the actual message data, and the connection ID.
  2389.  *
  2390.  * Parameters:
  2391.  *   type         The type of message to be built
  2392.  *   conn         Connection ID associated with this session
  2393.  *   stp          Pointer to the actual message data
  2394.  *
  2395.  * Returns:
  2396.  *                NULL, if unable to allocate memory for the message, or if
  2397.  *                      the specified message type is invalid
  2398.  *                a pointer to the newly-build message, otherwise
  2399.  *
  2400.  *
  2401.  * Description:
  2402.  *              Create a message data structure, and populate it as indicated.
  2403.  */
  2404.  
  2405. NIMsgPtr
  2406. MsgBuild(MsgType type, Uint4 conn, VoidPtr stp)
  2407. {
  2408.     NIMsgPtr            mp;
  2409.     
  2410.     if (! InitMsg())
  2411.         return NULL;
  2412.     mp = (NIMsgPtr) MemNew(sizeof(NIMessage));
  2413.     if (mp == NULL)
  2414.         return NULL;
  2415.     mp->type = type;
  2416.     mp->conid = conn;
  2417.     
  2418.     switch (mp->type) {
  2419.       case NI_ACK:
  2420.         mp->msun.ack = (NIAckPtr) stp;
  2421.         break;
  2422.         
  2423.       case NI_NACK:
  2424.         mp->msun.nack = (NINackPtr) stp;
  2425.         break;
  2426.         
  2427.       case NI_LOGIN:
  2428.         mp->msun.login = (NILoginPtr) stp;
  2429.         break;
  2430.         
  2431.       case NI_SVC_LIST:
  2432.         mp->msun.svclist = (NISvcListPtr) stp;
  2433.         break;
  2434.         
  2435.       case NI_SVC_REQUEST:
  2436.         mp->msun.svcreq = (NISvcReqPtr) stp;
  2437.         break;
  2438.         
  2439.       case NI_SVC_RESPONSE:
  2440.         mp->msun.svcresp = (NISvcRespPtr) stp;
  2441.         break;
  2442.         
  2443.       case NI_COMMAND:
  2444.         mp->msun.command = (NICmdPtr) stp;
  2445.         break;
  2446.         
  2447.       case NI_ACCT:
  2448.         mp->msun.acct = (NIAcctPtr) stp;
  2449.         break;
  2450.         
  2451.       case NI_CATALOG:
  2452.         mp->msun.catalog = (NICatalogPtr) stp;
  2453.         break;
  2454.         
  2455.       default:
  2456.         ni_errno = NIE_MSGUNK;
  2457.         StringCpy(ni_errtext, "unable to build");
  2458.         MemFree (mp);
  2459.         return NULL;
  2460.     }
  2461.     return mp;
  2462. } /* MsgBuild */
  2463.  
  2464.  
  2465.  
  2466. /*
  2467.  * Purpose:     Destroy the specified message
  2468.  *
  2469.  * Parameters:
  2470.  *   mp           A pointer to the message structure to be destroyed
  2471.  *
  2472.  * Returns:
  2473.  *                -1, if the specified pointer is NULL, or if the message
  2474.  *                    is of an unknown type
  2475.  *                0, otherwise
  2476.  *
  2477.  *
  2478.  * Description:
  2479.  *              Destroy the specified message, using the appropriate message
  2480.  *              destructor function.
  2481.  */
  2482.  
  2483. Int2 
  2484. MsgDestroy(NIMsgPtr mp)
  2485. {
  2486.     if (mp == NULL)
  2487.         return -1;
  2488.     
  2489.     switch (mp->type) {
  2490.       case NI_ACK:
  2491.         NI_DestroyMsgAck(mp->msun.ack);
  2492.         break;
  2493.         
  2494.       case NI_NACK:
  2495.         NI_DestroyMsgNack(mp->msun.nack);
  2496.         break;
  2497.         
  2498.       case NI_LOGIN:
  2499.         NI_DestroyMsgLogin(mp->msun.login);
  2500.         break;
  2501.         
  2502.       case NI_SVC_LIST:
  2503.         NI_DestroyMsgSvclist(mp->msun.svclist);
  2504.         break;
  2505.         
  2506.       case NI_SVC_REQUEST:
  2507.         NI_DestroyMsgSvcreq(mp->msun.svcreq);
  2508.         break;
  2509.         
  2510.       case NI_SVC_RESPONSE:
  2511.         NI_DestroyMsgSvcresp(mp->msun.svcresp);
  2512.         break;
  2513.         
  2514.       case NI_COMMAND:
  2515.         NI_DestroyMsgCmd(mp->msun.command);
  2516.         break;
  2517.         
  2518.       case NI_ACCT:
  2519.         NI_DestroyMsgAcct(mp->msun.acct);
  2520.         break;
  2521.         
  2522.       case NI_CATALOG:
  2523.         NI_DestroyMsgCatalog(mp->msun.catalog);
  2524.         break;
  2525.         
  2526.       default:
  2527.         ni_errno = NIE_MSGUNK;
  2528.         StringCpy(ni_errtext, "unable to destroy msg");
  2529.         MemFree(mp);
  2530.         return -1;
  2531.     }
  2532.  
  2533.     MemFree(mp);
  2534.     return 0;
  2535. } /* MsgDestroy */
  2536.  
  2537.  
  2538.  
  2539. /*
  2540.  * Purpose:     Create a message handle
  2541.  *
  2542.  * Returns:
  2543.  *                NULL, if unable to allocate the required memory, open
  2544.  *                    a socket, set the socket to non-blocking mode, or
  2545.  *                    initialize the ASN.1 I/O streams successfully
  2546.  *                a pointer to the new message handle, otherwise
  2547.  *
  2548.  *
  2549.  * Description:
  2550.  *              Create a "message" handle, which is the basic unit of message
  2551.  *              I/O. A message handle includes, among other things, a logical
  2552.  *              connection ID, a socket used for both input and output, ASN.1
  2553.  *              I/O stream pointers, and a queue of input data which has
  2554.  *              already been read from the socket, but has not yet been
  2555.  *              processed successfully using ASN.1.
  2556.  *
  2557.  * Note:
  2558.  *              This is currently the only place where conid is incremented,
  2559.  *              and therefore, the only place where conid is written to the
  2560.  *              Conid file.
  2561.  */
  2562.  
  2563. MHandPtr 
  2564. MsgMakeHandle(Boolean createSocket)
  2565. {
  2566.     MHandPtr    mh;
  2567.     
  2568.     if (! InitMsg()) {
  2569.         StringCpy(ni_errtext, "Network services ASN.1 initialization failed");
  2570.         ni_errno = NIE_ASN1SPECFAIL;
  2571.         return NULL;
  2572.     }
  2573.     if ((mh = (MHandPtr) MemNew(sizeof(MHandle))) == NULL) {
  2574.         StringCpy(ni_errtext, "unable to allocate new memory");
  2575.         return NULL;
  2576.     }
  2577.     mh->hostname = NULL;
  2578.     mh->conid = conid++;
  2579.     WriteConFile(conid);
  2580.     mh->seqno = 1;
  2581.     mh->sok = -1;
  2582.  
  2583.     if (createSocket) {
  2584.         if ((mh->sok = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) ==
  2585.             INVALID_SOCKET) {
  2586. #ifdef NETP_INET_NEWT
  2587.             SOCK_ERRNO = ABS(mh->sok);
  2588. #endif
  2589.             StringCpy(ni_errtext, sys_errlist[SOCK_INDEX_ERRNO]);
  2590.             MemFree(mh);
  2591.             return NULL;
  2592.         }
  2593.         if (NI_SETNONBLOCKING(mh->sok) == -1) {
  2594.             StringCpy(ni_errtext, sys_errlist[SOCK_INDEX_ERRNO]);
  2595.             MemFree(mh);
  2596.             return NULL;
  2597.         }
  2598.     }
  2599.     mh->r_timeout = NI_READ_TIMEOUT;
  2600.     mh->w_timeout = NI_WRITE_TIMEOUT;
  2601.     mh->state = NI_CREATED;
  2602.     mh->extra_proc_info = NULL;
  2603.     mh->read_filter = NULL;
  2604.     mh->write_filter = NULL;
  2605.     mh->write_filt_pass_thru = TRUE;
  2606.     mh->read_filt_pass_thru = TRUE;
  2607.     mh->readTimeoutHook = NULL;
  2608.     mh->writeTimeoutHook = NULL;
  2609.     mh->readTimer = NULL;
  2610.     mh->writeTimer = NULL;
  2611.     mh->peer = 0;
  2612.     if ((mh->raip = AsnIoNew((ASNIO_BIN | ASNIO_IN), (FILE *) NULL, (Pointer) mh, NI_AsnRead, NI_AsnWrite)) == NULL) {
  2613.         NI_CLOSESOCKET(mh->sok);
  2614.         StringCpy(ni_errtext, "unable to allocate new AsnIoPtr (raip)");
  2615.         MemFree(mh);
  2616.         return NULL;
  2617.     }
  2618.     if ((mh->waip = AsnIoNew((ASNIO_BIN | ASNIO_OUT), (FILE *) NULL, (Pointer) mh, NI_AsnRead, NI_AsnWrite)) == NULL) {
  2619.         AsnIoClose(mh->raip);
  2620.         NI_CLOSESOCKET(mh->sok);
  2621.         StringCpy(ni_errtext, "unable to allocate new AsnIoPtr (waip)");
  2622.         MemFree(mh);
  2623.         return NULL;
  2624.     }
  2625.     AsnIoSetBufsize(mh->waip, NI_BLOCKSIZE);
  2626.     mh->longjump = FALSE;
  2627.     mh->access_time = time(NULL);
  2628.     mh->have_blocked = FALSE;
  2629.     mh->num_queued_bytes = 0;
  2630.     mh->cur_index = 0;
  2631.     mh->queued_data_list = NULL;
  2632.     mh->unblocked_mode = FALSE;
  2633.     return mh; 
  2634. } /* MsgMakeHandle */
  2635.  
  2636.  
  2637.  
  2638. /*
  2639.  * Purpose:     Destroy the specified message handle
  2640.  *
  2641.  * Parameters:
  2642.  *   hp           A pointer to the message handle to be destroyed
  2643.  *
  2644.  * Returns:
  2645.  *                -1, if the specified pointer is NULL
  2646.  *                0, otherwise
  2647.  *
  2648.  *
  2649.  * Description:
  2650.  *              Destroy the specified message handle, close its socket,
  2651.  *              close the ASN streams, and free any associated queued data.
  2652.  */
  2653.  
  2654. Int2 
  2655. MsgDestroyHandle(MHandPtr hp)
  2656. {
  2657.     if (hp == NULL)
  2658.         return -1;
  2659.     NI_CLOSESOCKET(hp->sok);
  2660.     if (hp->hostname != NULL)
  2661.         MemFree(hp->hostname);
  2662.     NI_CancelTimer(hp->readTimer);
  2663.     NI_CancelTimer(hp->writeTimer);
  2664.     AsnIoClose(hp->raip);
  2665.     AsnIoClose(hp->waip);
  2666.     MsgFreeSavedData(hp);
  2667.     MemFree(hp);
  2668.     return 0;
  2669. } /* MsgDestroyHandle */
  2670.  
  2671.  
  2672.  
  2673. /*
  2674.  * Purpose:     Set "longjump" error mechanism
  2675.  *
  2676.  * Parameters:
  2677.  *   mh           A pointer to the message handle for which the "longjump"
  2678.  *                error is to be set.
  2679.  *
  2680.  *
  2681.  * Description:
  2682.  *              Set the ASN I/O error handler to be a function which will
  2683.  *              simply "longjump", and hence return control to the place at
  2684.  *              which setjmp() was last called. The "longjump" flag should
  2685.  *              be check by a setjmp() caller, prior to calling setjmp(), to
  2686.  *              assure that the error handling mechanism is in place.
  2687.  */
  2688.  
  2689. void 
  2690. MsgSetLJError(MHandPtr mh)
  2691. {
  2692.     AsnIoSetErrorMsg(mh->raip, NI_ASNIOError);
  2693.     AsnIoSetErrorMsg(mh->waip, NI_ASNIOError);
  2694.     mh->longjump = TRUE;
  2695. } /* MsgSetLJError */
  2696.  
  2697.  
  2698.  
  2699. /*
  2700.  * Purpose:     Set the "read" timeout for this message handle
  2701.  *
  2702.  * Parameters:
  2703.  *   mh           A pointer to the message handle for which the read timeout
  2704.  *                is to be set.
  2705.  *
  2706.  *
  2707.  * Description:
  2708.  *              Set the "read" timeout for this message handle. A default
  2709.  *              value is set-up at the time when the message handle is created.
  2710.  *
  2711.  * Note:
  2712.  *              This timeout is also used for the "hung" timeout.
  2713.  */
  2714.  
  2715. void 
  2716. MsgSetReadTimeout(MHandPtr mh, int t)
  2717. {
  2718.     mh->r_timeout = t;
  2719. } /* MsgSetReadTimeout */
  2720.  
  2721.  
  2722. /*
  2723.  * Purpose:     Set the "write" timeout for this message handle
  2724.  *
  2725.  * Parameters:
  2726.  *   mh           A pointer to the message handle for which the write timeout
  2727.  *                is to be set.
  2728.  *
  2729.  *
  2730.  * Description:
  2731.  *              Set the "write" timeout for this message handle. A default
  2732.  *              value is set-up at the time when the message handle is created.
  2733.  */
  2734.  
  2735. void 
  2736. MsgSetWriteTimeout(MHandPtr mh, int t)
  2737. {
  2738.     mh->w_timeout = t;
  2739. } /* MsgSetWriteTimeout */
  2740.  
  2741.  
  2742. /*
  2743.  * Purpose:     Set the filter parameters for this message handle
  2744.  *
  2745.  * Parameters:
  2746.  *   mh           A pointer to the message handle for which the parameters
  2747.  *                are to be set.
  2748.  *
  2749.  *   ex_proc      A pointer to an optional user-defined data structure to be
  2750.  *                used by the read and write filters.
  2751.  *
  2752.  *   wfilt        A write filter function, which may be used, e.g., to collect
  2753.  *                statistics, or to compress the data to be written.
  2754.  *
  2755.  *   rfilt        A read filter function, which may be used, e.g., to collect
  2756.  *                statistics, or to decompress the data which was read.
  2757.  *
  2758.  *   wfilt_pass   Indicates whether wfilt needs to modify the data buffer (e.g.,
  2759.  *                this will be FALSE if doing statistics only, but TRUE if
  2760.  *                doing data compression).
  2761.  *
  2762.  *   rfilt_pass   Indicates whether rfilt needs to return a modified data
  2763.  *                buffer (e.g., this will be FALSE if doing statistics only,
  2764.  *                but TRUE if doing data decompression).
  2765.  *
  2766.  *
  2767.  * Description:
  2768.  *              Set the I/O filters for this message handle. A default
  2769.  *              value (no filter) is set up at the time when the message
  2770.  *              handle is created.
  2771.  *
  2772.  * Note:
  2773.  *              It is the responsibility of the higher-level software (i.e.,
  2774.  *              not this module) to free any data associated with ex_proc.
  2775.  */
  2776.  
  2777. void
  2778. MsgSetFilters(MHandPtr mh, VoidPtr ex_proc, NI_WriteFilt wfilt,
  2779.               NI_ReadFilt rfilt, Boolean wfilt_pass, Boolean rfilt_pass)
  2780. {
  2781.     if (mh == NULL)
  2782.         return;
  2783.  
  2784.     mh->extra_proc_info = ex_proc;
  2785.     mh->write_filter = wfilt;
  2786.     mh->read_filter = rfilt;
  2787.     mh->write_filt_pass_thru = wfilt_pass;
  2788.     mh->read_filt_pass_thru = rfilt_pass;
  2789. }
  2790.  
  2791.  
  2792. /*
  2793.  * Purpose:     Set the timeout hooks for this message handle
  2794.  *
  2795.  * Parameters:
  2796.  *   mh           A pointer to the message handle for which the parameters
  2797.  *                are to be set.
  2798.  *
  2799.  *   rhook        A hook to be called when the read timeout expires
  2800.  *
  2801.  *   whook        A hook to be called when the write timeout expires
  2802.  *
  2803.  *
  2804.  * Description:
  2805.  *              Set the read and write timeout hooks for this message handle.
  2806.  *              A default value (no hook) is set up at the time when the
  2807.  *              message handle is created.
  2808.  *
  2809.  * Note:
  2810.  *              The write hook is currently usused (6/2/93).
  2811.  */
  2812.  
  2813. void
  2814. MsgSetTimeoutHooks(MHandPtr mh, NI_TimeoutHook rhook, NI_TimeoutHook whook)
  2815. {
  2816.     if (mh == NULL)
  2817.         return;
  2818.  
  2819.     mh->readTimeoutHook = rhook;
  2820.     mh->writeTimeoutHook = whook;
  2821. }
  2822.  
  2823. /*
  2824.  * Purpose:     Initialize the ASN.1 object loader for this module
  2825.  *
  2826.  * Parameters:
  2827.  *   none
  2828.  *
  2829.  *
  2830.  * Description:
  2831.  *              Dynamically load the ASN.1 static header, if necessary.
  2832.  */
  2833.  
  2834. static Boolean
  2835. InitMsg (void)
  2836. {
  2837.     static Boolean loaded = FALSE;
  2838.  
  2839.     if (loaded)
  2840.         return TRUE;
  2841.     if (! AsnLoad()) 
  2842.         return FALSE;
  2843.     loaded = TRUE;
  2844.     return TRUE;
  2845. }
  2846.  
  2847.  
  2848. /******************************************************************************/
  2849. /*                                                                            */
  2850. /*      Functions used by AsnTool for socket IO (readfunc and writefunc)      */
  2851. /*                                                                            */
  2852. /******************************************************************************/
  2853.  
  2854. /*
  2855.  * Purpose:     Read some data on behalf of the ASN.1 library
  2856.  *
  2857.  * Parameters:
  2858.  *   p            A pointer to the message handle structure
  2859.  *   buf          The buffer into which the data should be read
  2860.  *   len          Maximum number of bytes to be read
  2861.  *
  2862.  * Returns:
  2863.  *                0, if operating in "unblocked mode", and are unable to
  2864.  *                   read the requested amount of data
  2865.  *                -ETIMEOUT, if blocked, waiting for data to be available, but
  2866.  *                   none arrived before the read timeout expired
  2867.  *                -errno [ system error number ], for other errors
  2868.  *                the number of bytes read, otherwise
  2869.  *
  2870.  *
  2871.  * Description:
  2872.  *              This is the 'readfunc' function used by ASN.1 to read some
  2873.  *              data from the specified ASN.1 I/O stream.
  2874.  *
  2875.  *              First, try to read some data from the "queued data", i.e.,
  2876.  *              data which was read from the socket on a previous iteration,
  2877.  *              but ASN.1 processing failed because there was insufficient
  2878.  *              data.
  2879.  *
  2880.  *              Subsequently, try to read from the socket. If the data is
  2881.  *              unavailable, and running in "blocked" mode, wait for either
  2882.  *              the data to appear or for the read timeout to expire.
  2883.  *
  2884.  *              In the case where data is read successfully, store it in
  2885.  *              the "queued data" area.
  2886.  *
  2887.  *              Once data has been read successfully, optionally post-process
  2888.  *              it through a filter routine. This routine may, e.g., collect
  2889.  *              statistics or provide a de-compression mechanism. If it is
  2890.  *              a de-compression mechanism, any data which would not fit in
  2891.  *              the original buffer is stored in the "queued data" area, to
  2892.  *              be re-read by the next call to this function.
  2893.  */
  2894.  
  2895. Int2 LIBCALLBACK
  2896. NI_AsnRead(Pointer p, CharPtr buf, Uint2 len)
  2897. {
  2898.     MHandPtr        mh;
  2899.     int     bytesread;
  2900.     int     ready;
  2901.     time_t  secs0, secs1;
  2902.     fd_set  rfds;
  2903.     struct timeval  timeout;
  2904.     CharPtr extra_buf;
  2905.     Int4 extra_buf_len;
  2906.     NI_NetServHook activityHook;
  2907.  
  2908.     mh = (MHandPtr) p;
  2909.  
  2910.     /* always provide caller with queued data, if available */
  2911.     if (MsgHaveSavedData(mh))
  2912.     {
  2913.         return MsgReadSavedData(mh, buf, len);
  2914.     }
  2915.  
  2916.     mh->access_time = time(NULL);
  2917.  
  2918.     DisabVibrant();
  2919.  
  2920.     while ((bytesread = NI_READSOCKET(mh->sok, buf, len)) <= 0) {
  2921. #ifndef NETP_INET_PCNFS
  2922.         if (bytesread == 0) {
  2923.             break;
  2924.         }
  2925. #else
  2926.         SOCK_ERRNO = tk_geterrno (mh->sok);
  2927. #endif
  2928. #ifdef NETP_INET_NEWT
  2929.         SOCK_ERRNO = ABS(bytesread);
  2930. #endif
  2931.         switch (SOCK_ERRNO) {
  2932.           case EINTR:
  2933.             continue;
  2934.  
  2935.           case EAGAIN:
  2936. #if EAGAIN != EWOULDBLOCK
  2937.           case EWOULDBLOCK:
  2938. #endif /* EAGAIN != EWOULDBLOCK */
  2939.             if (mh->unblocked_mode)
  2940.             {
  2941.                 mh->have_blocked = TRUE;
  2942.                 EnabVibrant();
  2943.                 return 0;
  2944.             }
  2945.             FD_ZERO(&rfds);
  2946.             FD_SET(mh->sok, &rfds);
  2947.             secs0 = secs1 = time(NULL);
  2948.  
  2949.               RepeatSelect:
  2950.             /* a simple poll is effected when timeout.tv_sec == 0 */
  2951.             timeout.tv_sec = mh->r_timeout - (secs1 - secs0);
  2952.             timeout.tv_usec = 0;
  2953.             ready = NI_select(mh->sok + 1, &rfds, NULL, NULL, &timeout);
  2954.             if (ready > 0)
  2955.                 continue;
  2956.             if (ready == 0)
  2957.             {
  2958.                 EnabVibrant();
  2959.                 return (-ABS(ETIMEDOUT));
  2960.             }
  2961.             switch (SOCK_ERRNO) {
  2962.               case EINTR:
  2963.                 /* update the timeout because select() does not */
  2964.                 secs1 = time(NULL);
  2965.                 if (secs1 - secs0 > (time_t) mh->r_timeout)
  2966.                 secs1 = secs0 + mh->r_timeout;
  2967.                 goto RepeatSelect;
  2968.  
  2969.               default:
  2970.                 break;
  2971.             }
  2972.             EnabVibrant();
  2973.             return (-ABS(SOCK_ERRNO));
  2974.  
  2975.           default:
  2976.             EnabVibrant();
  2977.             return (-ABS(SOCK_ERRNO));
  2978.         }
  2979. #ifdef WIN_MSWIN
  2980. #ifdef NETP_INET_WSOCK
  2981.         {
  2982.             MSG msg;
  2983.  
  2984.             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  2985.             {
  2986.                 TranslateMessage(&msg);
  2987.                 DispatchMessage(&msg);
  2988.             }
  2989.         }
  2990. #else
  2991.         Yield();
  2992. #endif
  2993. #endif
  2994.     }
  2995.  
  2996.     EnabVibrant();
  2997.  
  2998.     extra_buf = NULL;
  2999.     if (mh->read_filter != NULL)
  3000.     {
  3001.         if (mh->read_filt_pass_thru)
  3002.         {
  3003.             mh->read_filter (mh, buf, bytesread, len, NULL, NULL);
  3004.         }
  3005.         else {
  3006.             bytesread = (int) mh->read_filter (mh, buf, bytesread, len,
  3007.                                                &extra_buf, &extra_buf_len);
  3008.         }
  3009.     }
  3010.  
  3011.     if ((activityHook = NI_ActivityHook()) != NULL)
  3012.     {
  3013.         activityHook (mh, NetServHook_read, bytesread);
  3014.     }
  3015.  
  3016.     /* save what we just read */
  3017.     MsgSaveData (mh, buf, bytesread);
  3018.  
  3019.     if (extra_buf != NULL)
  3020.     { /* there was some extra data which we didn't get to read */
  3021.        MsgSaveData (mh, extra_buf, (Uint2) extra_buf_len);
  3022.        mh->cur_index -= extra_buf_len; /* enqueue data for next read */
  3023.        MemFree (extra_buf);
  3024.        extra_buf = NULL;
  3025.     }
  3026.  
  3027.     return bytesread;
  3028. } /* NI_AsnRead */
  3029.  
  3030.  
  3031.  
  3032. /*
  3033.  * Purpose:     Write some data on behalf of the ASN.1 library
  3034.  *
  3035.  * Parameters:
  3036.  *   p            A pointer to the message handle structure
  3037.  *   buf          The buffer into which the data should be written
  3038.  *   len          Number of bytes to be written
  3039.  *
  3040.  * Returns:
  3041.  *                -ETIMEOUT, if unable to write the data before the write
  3042.  *                   timeout expired
  3043.  *                -errno [ system error number ], for other errors
  3044.  *                the number of bytes written, otherwise
  3045.  *
  3046.  *
  3047.  * Description:
  3048.  *              This is the 'writefunc' function used by ASN.1 to write some
  3049.  *              data to the specified ASN.1 I/O stream.
  3050.  *
  3051.  *              If unable to write the data immediately, block until it is
  3052.  *              possible to write the data, or until the write timeout expires.
  3053.  *
  3054.  *              The data to be output is optionally passed through a filter
  3055.  *              routine. This routine may, for example, collect statistics
  3056.  *              or compress the data to be written.
  3057.  *
  3058.  * Note:
  3059.  *              It is relatively unlikely that "writing" will block, thus
  3060.  *              causing the calling application to block. For "writing" to
  3061.  *              block, there would need to be flow control imposed in the
  3062.  *              TCP/IP protocol suite, which is an unlikely occurance when
  3063.  *              passing small quantities of data.
  3064.  */
  3065.  
  3066. Int2 LIBCALLBACK
  3067. NI_AsnWrite(Pointer p, CharPtr buf, Uint2 len)
  3068. {
  3069.     MHandPtr        mh;
  3070.     Int2    byteswrit, bytesleft;
  3071.     int     ready;
  3072.     fd_set  wfds;
  3073.     time_t  secs0, secs1 = 0;
  3074.     struct timeval  timeout;
  3075.     CharPtr newbuf;
  3076.     Uint2 newlen;
  3077.     CharPtr tmpbuf = NULL;
  3078.     NI_NetServHook activityHook;
  3079.     
  3080.     mh = (MHandPtr) p;
  3081.     mh->access_time = time(NULL);
  3082.  
  3083.     newbuf = buf;
  3084.     newlen = len;
  3085.     if (mh->write_filter != NULL)
  3086.     {
  3087.         if (mh->write_filt_pass_thru)
  3088.         { /* write filter is "pass-through only" */
  3089.             mh->write_filter (mh, buf, len, NULL);
  3090.         }
  3091.         else { /* write filter modifies buffer to be written */
  3092.             tmpbuf = (CharPtr) MemNew(len + 5);
  3093.             newlen = (Uint2) mh->write_filter(mh, buf, len, tmpbuf);
  3094.             newbuf = tmpbuf;
  3095.         }
  3096.     }
  3097.  
  3098.     if ((activityHook = NI_ActivityHook()) != NULL)
  3099.     {
  3100.         activityHook (mh, NetServHook_write, newlen);
  3101.     }
  3102.  
  3103.     DisabVibrant();
  3104.     
  3105.     for (bytesleft = newlen; bytesleft > 0; bytesleft -= byteswrit,
  3106.          newbuf += byteswrit) {
  3107.         while ((byteswrit = NI_WRITESOCKET(mh->sok, newbuf, bytesleft)) <= 0) {
  3108.         if (byteswrit == 0)
  3109.         {
  3110. #ifdef NETP_INET_NEWT
  3111.             /* this is a real kludge to deal with the fact that NEWT          */
  3112.             /* sometimes returns 0 on a send() for no good reason; we simulate*/
  3113.             /* that we were told that the send() would block                  */
  3114.             byteswrit = -EWOULDBLOCK;
  3115. #else
  3116.             WriteCleanup(tmpbuf);
  3117.             return 0;
  3118. #endif /* NETP_INET_NEWT */
  3119.         }
  3120.  
  3121. #ifdef NETP_INET_NEWT
  3122.         SOCK_ERRNO = ABS(byteswrit);
  3123. #endif
  3124. #ifdef NETP_INET_PCNFS
  3125.         SOCK_ERRNO = tk_geterrno (mh->sok);
  3126. #endif
  3127.  
  3128.         byteswrit = 0; /* don't allow byte count to become messed up */
  3129.  
  3130.         switch (SOCK_ERRNO) {
  3131.           case EINTR:
  3132.             continue;
  3133.             
  3134.           case EAGAIN:
  3135. #if EAGAIN != EWOULDBLOCK
  3136.             
  3137.           case EWOULDBLOCK:
  3138. #endif
  3139. #ifdef NETP_INET_NEWT
  3140.             /* work-around for bug in version 2.00 of NEWT; a select()*/
  3141.             /* will never recognize when it's O.K. to write to a      */
  3142.             /* socket                                                 */
  3143.             if (secs1 == 0)
  3144.             {
  3145.                 secs1 = secs0 = time(NULL);
  3146.             }
  3147.             else {
  3148.                 secs1 = time(NULL);
  3149.                 if (secs1 - secs0 > (time_t) mh->w_timeout)
  3150.                 {
  3151.                     WriteCleanup(tmpbuf);
  3152.                     return (-ABS(ETIMEDOUT));
  3153.                 }
  3154.             }
  3155.             break;
  3156. #endif
  3157.             FD_ZERO(&wfds);
  3158.             FD_SET(mh->sok, &wfds);
  3159.             secs0 = secs1 = time(NULL);
  3160.  
  3161.           RepeatSelect:
  3162.             /* a simple poll is effected when timeout.tv_sec == 0 */
  3163.             timeout.tv_sec = mh->w_timeout - (secs1 - secs0);
  3164.             timeout.tv_usec = 0;
  3165.             ready = NI_select(mh->sok + 1, NULL, &wfds, NULL, &timeout);
  3166.             if (ready > 0)
  3167.                 continue;
  3168.             if (ready == 0)
  3169.             {
  3170.                 WriteCleanup(tmpbuf);
  3171.                 return (-ABS(ETIMEDOUT));
  3172.             }
  3173.             switch (SOCK_ERRNO) {
  3174.               case EINTR:
  3175.                 /* update the timeout because select() does not */
  3176.                 secs1 = time(NULL);
  3177.                 if (secs1 - secs0 > (time_t) mh->w_timeout)
  3178.                     secs1 = secs0 + mh->w_timeout;
  3179.                 goto RepeatSelect;
  3180.               default:
  3181.                 break;
  3182.             }
  3183.             WriteCleanup(tmpbuf);
  3184.             return (-ABS(SOCK_ERRNO));
  3185.  
  3186.           default:
  3187.             WriteCleanup(tmpbuf);
  3188.             return (-ABS(SOCK_ERRNO));
  3189.         }
  3190. #ifdef WIN_MSWIN
  3191. #ifdef NETP_INET_WSOCK
  3192.         {
  3193.             MSG msg;
  3194.  
  3195.             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  3196.             {
  3197.                 TranslateMessage(&msg);
  3198.                 DispatchMessage(&msg);
  3199.             }
  3200.         }
  3201. #else
  3202.         Yield();
  3203. #endif
  3204. #endif
  3205.         }
  3206.     }
  3207.  
  3208.     WriteCleanup(tmpbuf);
  3209.     return (Int2)len;
  3210. } /* NI_AsnWrite */
  3211.  
  3212.  
  3213. /*
  3214.  * Purpose:     Clean-up for NI_AsnWrite
  3215.  *
  3216.  * Parameters:
  3217.  *   tmpbuf       Temporary buffer to be freed, if non-NULL
  3218.  *
  3219.  *
  3220.  * Description:
  3221.  *              Frees temporary buffer, and re-enables Vibrant for user
  3222.  *              input. Used because there are so many return paths from
  3223.  *              NI_AsnWrite.
  3224.  *
  3225.  */
  3226.  
  3227. static void
  3228. WriteCleanup (CharPtr tmpbuf)
  3229. {
  3230.     if (tmpbuf != NULL)
  3231.     {
  3232.         MemFree (tmpbuf);
  3233.     }
  3234.     EnabVibrant();
  3235. }
  3236.  
  3237.  
  3238. /*
  3239.  * Purpose:     ASN.1 Error handling
  3240.  *
  3241.  * Parameters:
  3242.  *   level        Error code to be returned
  3243.  *   str          Error text generated by ASN.1
  3244.  *
  3245.  *
  3246.  * Description:
  3247.  *              This is the error handling function used by ASN.1; it is called
  3248.  *              when any ASN.1 I/O error occurs.
  3249.  *
  3250.  *              When an ASN.1 I/O error occurs, this function stores the
  3251.  *              error text in a safe place, and "longjumps", returning
  3252.  *              control to a point where setjmp() was last called. This point
  3253.  *              should occur in a relatively high-level function (above the
  3254.  *              ASN.1 library).
  3255.  *
  3256.  * Note:
  3257.  *              Due to the implementation of setjmp()/longjmp(), if level is
  3258.  *              0, then the setjmp() caller will see the value 1; this
  3259.  *              mechanism is used to allow a setjmp() caller to distinguish
  3260.  *              between the case when they have just "set" the jump environment
  3261.  *              (return value == 0), and all other cases.
  3262.  */
  3263.  
  3264. void LIBCALLBACK
  3265. NI_ASNIOError(Int2 level, CharPtr str)
  3266. {
  3267.     StringCpy(ni_errtext, str);
  3268.     LongJump(ni_env, level);
  3269. } /* NI_ASNIOError */
  3270.  
  3271.  
  3272.  
  3273. #if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
  3274.  
  3275. /*
  3276.  * Purpose:     Implementation of blocked select() for use with NEWT and WSOCK
  3277.  *
  3278.  * Parameters:
  3279.  *   width        "width" of file descriptor bits maps
  3280.  *   rfds         Read file descriptor bit maps
  3281.  *   wfds         Write file descriptor bit maps
  3282.  *   xfds         Exception file descriptor bit maps
  3283.  *
  3284.  * Returns:
  3285.  *                0, if the timeout period elapses
  3286.  *                -1, if an error occurred
  3287.  *                the number of available file descriptors (selected file
  3288.  *                  descriptors which are available for processing), otherwise
  3289.  *
  3290.  *
  3291.  * Description:
  3292.  *              Provide a "blocked" select() mechanism, because NEWT does
  3293.  *              not provide one.
  3294.  *
  3295.  * Note:
  3296.  *              When calling select(), the width of the file descriptor
  3297.  *              maps is increased by one, to handle an off-by-one error
  3298.  *              associated with the NEWT library.
  3299.  *
  3300.  *              This function is used in WinSock (rather than WinSock's
  3301.  *              select function) to ensure that message removal/dispatching
  3302.  *              is done in a manner which does not interfere with scrollbar
  3303.  *              management.
  3304.  */
  3305.  
  3306. int 
  3307. NI_poll_select(int width, fd_set PNTR rfds, fd_set PNTR wfds, fd_set PNTR xfds, struct timeval PNTR timeout)
  3308. {
  3309.     fd_set      trfds, twfds, txfds;
  3310.     int         rdy;
  3311.     time_t      t_end;
  3312.     struct timeval tmout;
  3313.     
  3314.     if (rfds != NULL)
  3315.         Nlm_MemCopy(&trfds, rfds, sizeof(trfds));
  3316.     if (wfds != NULL)
  3317.         Nlm_MemCopy(&twfds, wfds, sizeof(twfds));
  3318.     if (xfds != NULL)
  3319.         Nlm_MemCopy(&txfds, xfds, sizeof(txfds));
  3320.     
  3321.     t_end = timeout->tv_sec + Nlm_GetSecs();
  3322.     tmout.tv_sec = 0;
  3323.     tmout.tv_usec = 0;
  3324. #ifdef NETP_INET_WSOCK
  3325.     width--;
  3326. #endif
  3327.     while  (Nlm_GetSecs() < t_end) {
  3328.         if (rfds != NULL)
  3329.             Nlm_MemCopy(rfds, &trfds, sizeof(trfds));
  3330.         if (wfds != NULL)
  3331.             Nlm_MemCopy(wfds, &twfds, sizeof(twfds));
  3332.         if (xfds != NULL)
  3333.             Nlm_MemCopy(xfds, &txfds, sizeof(txfds));
  3334.         
  3335. #ifdef NETP_INET_WSOCK
  3336.         {
  3337.             MSG msg;
  3338.             Boolean done = FALSE;
  3339.  
  3340.             /* get all the available messages, avoiding WM_LBUTTONUP since  */
  3341.             /* this will cause scroll bars to hang, for some unknown reason */
  3342.             while (! done)
  3343.             {
  3344.                 done = TRUE;
  3345.                 if (PeekMessage(&msg, NULL, 0, WM_LBUTTONUP-1, PM_REMOVE))
  3346.                 {
  3347.                     done = FALSE;
  3348.                     TranslateMessage(&msg);
  3349.                     DispatchMessage(&msg);
  3350.                 }
  3351.                 if (PeekMessage(&msg, NULL, WM_LBUTTONUP+1, 0xffff, PM_REMOVE))
  3352.                 {
  3353.                     done = FALSE;
  3354.                     TranslateMessage(&msg);
  3355.                     DispatchMessage(&msg);
  3356.                 }
  3357.             }
  3358.         }
  3359. #else
  3360.         Yield();
  3361. #endif
  3362.         /* select with (width + 1) because NetManage boundary condition error */
  3363.         
  3364.         if ((rdy = select((width + 1), rfds, wfds, xfds, &tmout)) != 0) {
  3365.             if (rdy < 0) {              /* error */
  3366. #ifdef NETP_INET_NEWT
  3367.                 errno = ABS(rdy);
  3368. #endif
  3369.                 rdy = -1;
  3370.             }
  3371.             return rdy;
  3372.         }
  3373.  
  3374.     }
  3375.     return 0;   /* timed out */
  3376. } /* NI_poll_select */
  3377.  
  3378. #endif
  3379.  
  3380.  
  3381. #ifdef NI_BLOCK_WITH_FUNCTION
  3382.  
  3383.  
  3384. /*
  3385.  * Purpose:     Implementation of setting non-blocked-socket mode for platforms
  3386.  *              for which it is difficult to perform this functionality within
  3387.  *              a macro.
  3388.  *
  3389.  * Parameters:
  3390.  *   fd           Socket file descriptor
  3391.  *
  3392.  */
  3393.  
  3394. int
  3395. NI_SetNonBlocking (int fd)
  3396. {
  3397.   int mode = 1;
  3398.  
  3399. #ifdef NETP_INET_WSOCK
  3400.   u_long lmode = 1;
  3401.   return ioctlsocket (fd, FIONBIO, &lmode);
  3402. #endif
  3403.  
  3404. #ifdef NETP_INET_PCNFS
  3405.   return tk_ioctl (fd, FIONBIO, &mode);
  3406. #endif
  3407. #ifdef NETP_INET_TGV
  3408.   return socket_ioctl (fd, FIONBIO, &mode);
  3409. #endif
  3410. #ifdef NETP_INET_TWG
  3411.   /**************************************************************************/
  3412.   /* WARNING: THIS IS CURRENTLY NOT IMPLEMENTED PROPERLY BECAUSE WE (W.     */
  3413.   /*          GILBERT/J. EPSTEIN) ARE NOT ABLE TO MAKE NETWORK SERVICES     */
  3414.   /*          OPERATE PROPERLY IN NON-BLOCKING MODE.  AT SOME FUTURE DATE,  */
  3415.   /*          THE REMAINDER OF NETWORK SERVICES SHOULD BE DEBUGGED AND THE  */
  3416.   /*          FOLLOWING LINE SHOULD READ: lmode = 1                         */
  3417.   /*                                          17 June 1993                  */
  3418.   /**************************************************************************/
  3419.   long lmode = 0;
  3420.   return ioctl (fd, FIONBIO, &lmode);
  3421. #endif
  3422. #ifdef NETP_INET_UCX
  3423.   /**************************************************************************/
  3424.   /* WARNING: THIS IS CURRENTLY UNIMPLEMENTED BECAUSE IT IS NOT CLEAR THAT  */
  3425.   /*          IT IS POSSIBLE TO SPECIFY BLOCKING/NONBLOCKING MODE FOR UCX   */
  3426.   /*                                          22 June 1993                  */
  3427.   /**************************************************************************/
  3428.   return 0;
  3429. #endif
  3430. }
  3431.  
  3432. /*
  3433.  * Purpose:     Implementation of setting blocked-socket mode for platforms
  3434.  *              for which it is difficult to perform this functionality within
  3435.  *              a macro.
  3436.  *
  3437.  * Parameters:
  3438.  *   fd           Socket file descriptor
  3439.  *
  3440.  */
  3441.  
  3442. int
  3443. NI_SetBlocking (int fd)
  3444. {
  3445.   int mode = 0;
  3446.  
  3447. #ifdef NETP_INET_WSOCK
  3448.   u_long lmode = 0;
  3449.   return ioctlsocket (fd, FIONBIO, &lmode);
  3450. #endif
  3451.  
  3452. #ifdef NETP_INET_PCNFS
  3453.   return tk_ioctl (fd, FIONBIO, &mode);
  3454. #endif
  3455. #ifdef NETP_INET_TGV
  3456.   return socket_ioctl (fd, FIONBIO, &mode);
  3457. #endif
  3458. #ifdef NETP_INET_TWG
  3459.   long lmode = 0;
  3460.   return ioctl (fd, FIONBIO, &lmode);
  3461. #endif
  3462. #ifdef NETP_INET_UCX
  3463.   /**************************************************************************/
  3464.   /* WARNING: THIS IS CURRENTLY UNIMPLEMENTED BECAUSE IT IS NOT CLEAR THAT  */
  3465.   /*          IT IS POSSIBLE TO SPECIFY BLOCKING/NONBLOCKING MODE FOR UCX   */
  3466.   /*                                          22 June 1993                  */
  3467.   /**************************************************************************/
  3468.   return 0;
  3469. #endif
  3470. }
  3471.  
  3472. #endif /* BLOCK_WITH_FUNCTION */
  3473.  
  3474.  
  3475. /*
  3476.  * Purpose:     Test as to whether there's available data already enqueued
  3477.  *
  3478.  * Parameters:
  3479.  *   mh           Pointer to "message handle" data structure
  3480.  *
  3481.  * Returns:
  3482.  *                FALSE, if there is no data already enqueued
  3483.  *                TRUE, otherwise
  3484.  *
  3485.  *
  3486.  * Description:
  3487.  *              Determine whether there is currently enqueued data on a
  3488.  *              "message handle" data structure.
  3489.  */
  3490.  
  3491. static Boolean
  3492. MsgHaveSavedData(MHandPtr mh)
  3493. {
  3494.     if (!mh->unblocked_mode)
  3495.         return FALSE;
  3496.     if (mh->queued_data_list == NULL)
  3497.         return FALSE;
  3498.     if (mh->num_queued_bytes <= 0)
  3499.         return FALSE;
  3500.     return (mh->cur_index < mh->num_queued_bytes);
  3501. }
  3502.  
  3503.  
  3504. /*
  3505.  * Purpose:     Read data which was previously stored in this "message handle"
  3506.  *
  3507.  * Parameters:
  3508.  *   mh           Pointer to "message handle" data structure
  3509.  *   buf          Buffer where data should be stored
  3510.  *   len          Maximum number of bytes to read out
  3511.  *
  3512.  * Returns:
  3513.  *                the number of bytes read from the enqueued data list
  3514.  *
  3515.  *
  3516.  * Description:
  3517.  *              Return up to len bytes of enqueued data, by traversing
  3518.  *              the enqueued data structure, beginning with the location
  3519.  *              where the "current byte" pointer is currently pointing.
  3520.  *
  3521.  * Note:
  3522.  *              The enqueued data is stored in a list of chained blocks, where
  3523.  *              at all times, all the blocks are full, except (possibly) the
  3524.  *              last block.
  3525.  */
  3526.  
  3527. #define MSG_READ_BLOCK_SIZE 1024
  3528.  
  3529. static int
  3530. MsgReadSavedData(MHandPtr mh, CharPtr buf, Uint2 len)
  3531. {
  3532.     NodePtr startpt;
  3533.     NodePtr blk;
  3534.     int     addl_queue_data;
  3535.     int     local_index;
  3536.     int     bytes_copied;
  3537.     int     data_in_this_block;
  3538.     int     bytes_to_copy;
  3539.  
  3540.     if (mh->queued_data_list == NULL || len <= 0 || mh->num_queued_bytes == 0)
  3541.         return 0;
  3542.     blk = startpt = mh->queued_data_list;
  3543.     addl_queue_data = mh->num_queued_bytes - mh->cur_index;
  3544.     local_index = 0;
  3545.     bytes_copied = 0;
  3546.  
  3547.     /* traverse the portion of the list which is necessary to get past */
  3548.     /* the current "file" pointer, and then copy up to len bytes of    */
  3549.     /* data from the remaining blocks                                  */
  3550.     do {
  3551.         /* if ( this is the last block ) then */
  3552.         if (mh->num_queued_bytes - local_index < MSG_READ_BLOCK_SIZE)
  3553.             data_in_this_block = mh->num_queued_bytes % MSG_READ_BLOCK_SIZE;
  3554.         else
  3555.             data_in_this_block = MSG_READ_BLOCK_SIZE;
  3556.  
  3557.         /* if ( there is more data to be skipped over ) then */
  3558.         if (local_index < mh->cur_index)
  3559.         { /* there is more data to be skipped over */
  3560.             if (local_index + data_in_this_block <= mh->cur_index)
  3561.             { /* skip this block */
  3562.                 local_index += data_in_this_block;
  3563.                 continue;
  3564.             }
  3565.             else { /* skip a portion of this block, and copy the remainder */
  3566.                 data_in_this_block -= (mh->cur_index - local_index);
  3567.                 local_index = mh->cur_index;
  3568.             }
  3569.         }
  3570.  
  3571.         bytes_to_copy = MIN((int) len, data_in_this_block);
  3572.         MemCopy(buf, blk->elem, bytes_to_copy);
  3573.         buf += bytes_to_copy;
  3574.         len -= bytes_to_copy;
  3575.         bytes_copied += bytes_to_copy;
  3576.         mh->cur_index += bytes_to_copy;
  3577.         local_index += bytes_to_copy;
  3578.     } while ( (blk = ListGetNext(blk)) != startpt && len > 0);
  3579.  
  3580.     return bytes_copied;
  3581. }
  3582.  
  3583.  
  3584.  
  3585. /*
  3586.  * Purpose:     Store len bytes of data from a buffer, for future use
  3587.  *
  3588.  * Parameters:
  3589.  *   mh           Pointer to "message handle" data structure
  3590.  *   buf          Buffer of data to be copied
  3591.  *   len          Number of bytes to save
  3592.  *
  3593.  *
  3594.  * Description:
  3595.  *              Store len bytes of data at the end of a list of "enqueued data."
  3596.  *              After finding the current end of the queue, data is added
  3597.  *              to the final block (up to its capacity), and then, if needed,
  3598.  *              additional blocks are allocated to store the remaining data.
  3599.  */
  3600.  
  3601. static void
  3602. MsgSaveData(MHandPtr mh, CharPtr buf, Uint2 len)
  3603. {
  3604.     NodePtr tail;
  3605.     int     bytes_to_copy;
  3606.     int     starting_byte;
  3607.     CharPtr newdata;
  3608.  
  3609.     if (len == 0 || !mh->unblocked_mode)
  3610.         return;
  3611.  
  3612.     /* get to the correct place in the list, and then start storing */
  3613.  
  3614.     tail = mh->queued_data_list;
  3615.  
  3616.     /* point to tail of list; in a ring, the element before the head is the */
  3617.     /* tail                                                                 */
  3618.     if (tail != NULL)
  3619.         tail = tail->last;
  3620.  
  3621.     /* if ( more room in the current element ) then */
  3622.     if ((starting_byte = mh->num_queued_bytes % MSG_READ_BLOCK_SIZE) != 0)
  3623.     {
  3624.         bytes_to_copy = MIN(MSG_READ_BLOCK_SIZE - starting_byte, (int) len);
  3625.         newdata = (CharPtr) tail->elem;
  3626.         MemCopy (&newdata[starting_byte], buf, bytes_to_copy);
  3627.         len -= bytes_to_copy;
  3628.         buf += len;
  3629.         mh->num_queued_bytes += bytes_to_copy;
  3630.     }
  3631.  
  3632.     /* while ( there is more data to be copied ) */
  3633.     while (len > 0)
  3634.     { /* create a new element, and copy data into that element */
  3635.  
  3636.         newdata = MemNew(MSG_READ_BLOCK_SIZE);
  3637.         bytes_to_copy = MIN(MSG_READ_BLOCK_SIZE, len);
  3638.         MemCopy (newdata, buf, bytes_to_copy);
  3639.         buf += bytes_to_copy;
  3640.         len -= bytes_to_copy;
  3641.         mh->num_queued_bytes += bytes_to_copy;
  3642.         tail = ListInsert(newdata, tail);
  3643.     }
  3644.  
  3645.     mh->cur_index = mh->num_queued_bytes;
  3646.  
  3647.     if (tail == NULL)
  3648.         mh->queued_data_list = NULL;
  3649.     else
  3650.         mh->queued_data_list = tail->next;
  3651. }
  3652.  
  3653.  
  3654.  
  3655. /*
  3656.  * Purpose:     Free data associated with an "enqueued data list"
  3657.  *
  3658.  * Parameters:
  3659.  *   mh           Pointer to "message handle" data structure
  3660.  *
  3661.  *
  3662.  * Description:
  3663.  *              Free all the message elements associated with a list of
  3664.  *              enqueued data, and set other message handle elements to
  3665.  *              appropriate values such that software accessing those structures
  3666.  *              will not, erroneously, think that there is valid enqueued data
  3667.  *              in the structure.
  3668.  */
  3669.  
  3670. static void
  3671. MsgFreeSavedData (MHandPtr mh)
  3672. {
  3673.     NodePtr np;
  3674.     CharPtr elem;
  3675.  
  3676.     mh->unblocked_mode = FALSE;
  3677.     mh->have_blocked = FALSE;
  3678.     mh->num_queued_bytes = 0;
  3679.     mh->cur_index = 0;
  3680.  
  3681.     np = mh->queued_data_list;
  3682.  
  3683.     mh->queued_data_list = NULL;
  3684.  
  3685.     while (np != NULL)
  3686.     {
  3687.         elem = (CharPtr) np->elem;
  3688.         if (elem != NULL)
  3689.             MemFree (elem);
  3690.         np = ListDelete(np);
  3691.     }
  3692. }
  3693.  
  3694.  
  3695. /*
  3696.  * Purpose:     Set and pop the hour-glass cursor
  3697.  *
  3698.  * Parameters:
  3699.  *   none
  3700.  *
  3701.  * Description:
  3702.  *              According to the NEWT/NetManage documentation, it is
  3703.  *              beneficial to make the cursor into an hourglass to block-out
  3704.  *              unwanted events during some socket calls.
  3705.  */
  3706.  
  3707. #if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
  3708. static HCURSOR saveCursor = NULL;
  3709.  
  3710. static void SetHourGlass(void)
  3711. {
  3712. #ifdef NETP_INET_NEWT
  3713.    static HCURSOR hourCursor;
  3714.  
  3715.    hourCursor = LoadCursor(NULL, IDC_WAIT);
  3716.    saveCursor = SetCursor(hourCursor);
  3717. #endif
  3718. }
  3719.  
  3720. static void PopHourGlass(void)
  3721. {
  3722. #ifdef NETP_INET_NEWT
  3723.    if (saveCursor != NULL)
  3724.       SetCursor(saveCursor);
  3725. #endif
  3726. }
  3727. #endif /* NETP_INET_NEWT */
  3728.