home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / MacTCP Library 1.1 / UDP⁄TCP Probe ƒ / Source ƒ / Probes.c next >
Encoding:
C/C++ Source or Header  |  1995-12-04  |  13.7 KB  |  757 lines  |  [TEXT/SPM ]

  1. /*
  2.     Probes.c
  3.     
  4.     Handles the actual probing of the host.
  5.     
  6.     06/27/95 dn - Created.
  7.     11/28/95 mc - converted to CodeWarrior
  8.     12/04/95 dn - Prep'd for Apprentice 4
  9.     
  10. */
  11.  
  12. #include <SpinLib.h>
  13. #include <MyTCPIncludes.h>
  14.  
  15. #if defined(SYMANTEC_C)||defined(THINK_C)
  16. #else
  17. #include <SIOUX.h>
  18. #include <stdio.h>
  19. #endif
  20.  
  21. #include "UDP Probe.h"
  22. #include "Probes.h"
  23.  
  24. Boolean gProbing=false;
  25. short gProbes=0;
  26.  
  27. OSErr InitProbes(void){
  28.     OSErr err=noErr;
  29.     
  30.     // not really much to do...
  31.     err=SpinInit();
  32.     
  33.     gProbes=0;
  34.     gProbing=false;
  35.     
  36.     return err;
  37. }
  38.  
  39. OSErr CleanupProbes(void){
  40.     OSErr err=noErr;
  41.     
  42.     if (gProbing){
  43.         // if we are currently probing a host, we need to stop it
  44.         SpinStart(1);
  45.         err=StopProbe();
  46.         SpinStop();
  47.     }
  48.     
  49.     err=SpinCleanup();
  50.     
  51.     return err;
  52. }
  53.  
  54. static Boolean gStrToAddrDone;
  55.  
  56. static pascal void StrToAddrDone(HostInfoPtr hostInfoPtr, char* userDataPtr){
  57.     
  58.     gStrToAddrDone=true;
  59. }
  60.  
  61. OSErr StartProbe(DialogPtr dlg){
  62.     OSErr err=noErr;
  63.     Handle h;
  64.     short i;
  65.     Rect r;
  66.     Str255 hostStr, portStr, timeoutStr, textStr;
  67.     ip_addr host;
  68.     short port;
  69.     short timeout;
  70.     char* txt;
  71.     
  72.     // if continuing...
  73.     if (dlg!=(DialogPtr)0L){
  74.         // start spinning the cursor
  75.         SpinStart(1);
  76.         
  77.         // extract information from the dialog...
  78.         GetDItem(dlg,3,&i,&h,&r);
  79.         GetIText(h,hostStr);
  80.         
  81.         GetDItem(dlg,4,&i,&h,&r);
  82.         GetIText(h,portStr);
  83.         
  84.         GetDItem(dlg,5,&i,&h,&r);
  85.         GetIText(h,timeoutStr);
  86.         
  87.         GetDItem(dlg,6,&i,&h,&r);
  88.         GetIText(h,textStr);
  89.         
  90.         // do the required conversions...
  91.         {
  92.             // convert host name to ip_addr
  93.             char* cp;
  94.             HostInfo theHost;
  95.             HostInfoUPP hiupp;
  96.             
  97.             hostStr[hostStr[0]+1]=0;
  98.             cp=(char*)&(hostStr[1]);
  99.             
  100.             gStrToAddrDone=false;
  101.             
  102.             hiupp=NewHostInfoProc(StrToAddrDone);
  103.             err=StrToAddr(cp,&theHost,hiupp,(char*)0L);
  104.             
  105.             if ((err==-1)||(err==cacheFault)){
  106.                 // not done yet...
  107.                 EventRecord er;
  108.                 
  109.                 while (!gStrToAddrDone){
  110.                     // give the system some time...
  111.                     if (WaitNextEvent(everyEvent,&er,100,(RgnHandle)0)){
  112.                         if (er.what==keyDown){
  113.                             // check for command-period
  114.                             char ch;
  115.                             
  116.                             ch=er.message&charCodeMask;
  117.                             
  118.                             if ((er.modifiers&cmdKey)&&(ch=='.')){
  119.                                 // the user wants to cancel this operation...
  120.                                 HandleError("\pCanceling probe",0);
  121.                                 
  122.                                 SpinStop();
  123.                                 DisposeHostInfoProc(hiupp);
  124.                                 return noErr;
  125.                             }
  126.                         } else {
  127.                             SysBeep(5); // notify of the error...
  128.                         }
  129.                     }
  130.                 }
  131.             } else if (err!=noErr){
  132.                 // error calling StrToAddr
  133.                 SpinStop();
  134.                 DisposeHostInfoProc(hiupp);
  135.                 
  136.                 HandleError("\pStrToAddr returns error",err);
  137.                 
  138.                 return err;
  139.             }
  140.             
  141.             DisposeHostInfoProc(hiupp);
  142.             
  143.             // ah, the name has been converted, just take it out of the HostInfo record...
  144.             host=theHost.addr[0];
  145.             err=theHost.rtnCode;
  146.         }
  147.         {
  148.             // convert port string to a short
  149.             // convert timeout string to a short
  150.             long tval;
  151.             
  152.             StringToNum(portStr,&tval);
  153.             port=LoWord(tval);
  154.             
  155.             StringToNum(timeoutStr,&tval);
  156.             timeout=LoWord(tval);
  157.         }
  158.         {
  159.             // copy text to a c string
  160.             txt=(char*)NewPtr(textStr[0]+2);
  161.             BlockMoveData((Ptr)textStr,(Ptr)txt,textStr[0]+2);
  162.             
  163.             MyP2CStr((StringPtr)txt);
  164.         }
  165.         
  166.         // if no errors handle the probe
  167.         if (err==noErr){
  168.             GetDItem(dlg,11,&i,&h,&r);
  169.             
  170.             if (GetCtlValue((ControlHandle)h)) // do a udp probe
  171.                 err=Probe(host,port,timeout,txt);
  172.             else // do a tcp probe
  173.                 err=TCPProbe(host,port,timeout,txt);
  174.         }
  175.         
  176.         SpinStop();
  177.     }
  178.     
  179.     return err;
  180. }
  181.  
  182. static StreamPtr list[200];
  183. static short nlist=0;
  184. static Boolean gDataArrived;
  185.  
  186. static StreamPtr active[200];
  187. static short aque=0;
  188.  
  189. static StreamPtr tlist[200];
  190. static short tnlist=0;
  191. static Boolean gtDataArrived;
  192.  
  193. static StreamPtr tactive[200];
  194. static short taque=0;
  195.  
  196. static ip_addr thosts[200];
  197. static short tports[200];
  198.  
  199. static pascal void UDPNotify(StreamPtr udp,unsigned short code,Ptr user,ICMPReport* icmp){
  200.     
  201.     if (code==UDPDataArrival){
  202.         list[nlist]=udp;
  203.         nlist++;
  204.         
  205.         gDataArrived=true;
  206.     }
  207. }
  208.  
  209. static short gterm=0;
  210.  
  211. static pascal void TCPNotify(StreamPtr tcp,unsigned short code,Ptr user,unsigned short term,ICMPReport* icmp){
  212.     register short loop=0;
  213.     
  214.     if (code==TCPDataArrival){
  215.         while (loop<tnlist){
  216.             if (tlist[loop]==tcp)
  217.                 return;
  218.             loop++;
  219.         }
  220.         
  221.         // if we get here then tcp is not yet in the list...
  222.         
  223.         tlist[tnlist]=tcp;
  224.         tnlist++;
  225.         
  226.         gtDataArrived=true;
  227.     } else if (code==TCPTerminate)
  228.         gterm=term;
  229. }
  230.  
  231. OSErr HandleDataStream(StreamPtr sp){
  232.     OSErr err=noErr;
  233.     char* buffer;
  234.     long buflen;
  235.     UDPiopbPtr udp;
  236.     ip_addr host;
  237.     short port;
  238.     
  239.     udp=NewUDPiopbPtr();
  240.     
  241.     udp->udpStream=sp;
  242.     udp->ioCRefNum=gMacTCP;
  243.     udp->csParam.receive.timeOut=5;
  244.     udp->csParam.receive.secondTimeStamp=0;
  245.     
  246.     err=UDP_Read(udp,false);
  247.     
  248.     host=udp->csParam.receive.remoteHost;
  249.     port=udp->csParam.receive.remotePort;
  250.     
  251.     if (err!=noErr){
  252.         DisposeUDPiopbPtr(udp);
  253.         HandleError("\pError receiving UDP data.",err);
  254.         return err;
  255.     }
  256.     
  257.     if (udp->csParam.receive.rcvBuffLen>0){
  258.         // data is available...
  259.         buflen=udp->csParam.receive.rcvBuffLen;
  260.         
  261.         buffer=(char*)NewPtr(buflen+5);
  262.         
  263.         BlockMoveData((Ptr)udp->csParam.receive.rcvBuff,(Ptr)buffer+1,buflen);
  264.         
  265.     } else
  266.         buflen=0L;
  267.     
  268.     err=UDP_BfrReturn(udp,false);
  269.     
  270.     // all data has been read and the buffer has been returned.
  271.     // it is now ok to get rid of the stream.
  272.     
  273.     udp->ioCRefNum=gMacTCP;
  274.     udp->udpStream=sp;
  275.     {
  276.         register short loop=0;
  277.         
  278.         while (loop<200){
  279.             if (active[loop]==sp){
  280.                 active[loop]=(StreamPtr)-1;
  281.                 break;
  282.             }
  283.             loop++;
  284.         }
  285.     }
  286.     
  287.     UDP_Release(udp,false);
  288.     
  289.     gProbes--;
  290.     if (gProbes==0)
  291.         gProbing=false;
  292.     
  293.     DisposeUDPiopbPtr(udp);
  294.     
  295.     if (err==noErr){
  296.         // Display the text...
  297.         err=ReportData(buffer,buflen,host,port);
  298.     }
  299.     
  300.     return err;
  301. }
  302.  
  303. OSErr HandleTCPDataStream(StreamPtr sp){
  304.     OSErr err=noErr;
  305.     char* buffer;
  306.     long buflen;
  307.     TCPiopbPtr tcp;
  308.     rdsEntry rds[5];
  309.     ip_addr host;
  310.     short port;
  311.     short term;
  312.     
  313.     tcp=NewTCPiopbPtr();
  314.     
  315.     // no error, prepare to receive data
  316.     rds[4].length=0;
  317.     rds[4].ptr=(char*)0;
  318.     
  319.     // now fetch the data...
  320.     tcp->tcpStream=sp;
  321.     tcp->ioCRefNum=gMacTCP;
  322.     tcp->ioCompletion=(TCPIOCompletionUPP)0;
  323.     tcp->csParam.receive.commandTimeoutValue=0;
  324.     tcp->csParam.receive.rdsPtr=(char*)rds;
  325.     tcp->csParam.receive.rdsLength=4;
  326.     
  327.     err=TCP_NoCopyRcv(tcp,true);
  328.     err=tcp->ioResult;
  329.     
  330.     if (err!=noErr){
  331.         DisposeTCPiopbPtr(tcp);
  332.         HandleError("\pError receiving TCP data.",err);
  333.         return err;
  334.     }
  335.     
  336.     // the data has been received...
  337.     
  338.     if (rds[0].length>0){
  339.         // data is available...
  340.         buflen=rds[0].length;
  341.         
  342.         buffer=(char*)NewPtr(buflen+5);
  343.         
  344.         BlockMoveData((Ptr)rds[0].ptr,(Ptr)buffer+1,buflen);
  345.         
  346.     } else
  347.         buflen=0L;
  348.     
  349.     tcp->tcpStream=sp;
  350.     tcp->ioCRefNum=gMacTCP;
  351.     tcp->csParam.receive.rdsPtr=(char*)rds;
  352.     
  353.     err=TCP_RcvBfrReturn(tcp,false);
  354.     
  355.     if (err!=noErr)
  356.         HandleError("\pError returning TCP buffers.",err);
  357.     err=noErr;
  358.     
  359.     // all data has been read and the buffer has been returned.
  360.     // it is now ok to get rid of the stream.
  361.     
  362.     tcp->ioCRefNum=gMacTCP;
  363.     tcp->tcpStream=sp;
  364.     {
  365.         register short loop=0;
  366.         
  367.         while (loop<200){
  368.             if (tactive[loop]==sp){
  369.                 tactive[loop]=(StreamPtr)-1;
  370.                 host=thosts[loop];
  371.                 port=tports[loop];
  372.                 break;
  373.             }
  374.             loop++;
  375.         }
  376.     }
  377.     
  378.     tcp->tcpStream=sp;
  379.     tcp->ioCRefNum=gMacTCP;
  380.     tcp->csParam.close.ulpTimeoutValue=0;
  381.     tcp->csParam.close.ulpTimeoutAction=0;
  382.     tcp->csParam.close.validityFlags=0;
  383.     
  384.     TCP_Close(tcp,false);
  385.     
  386.     tcp->tcpStream=sp;
  387.     tcp->ioCRefNum=gMacTCP;
  388.     
  389.     TCP_Release(tcp,false);
  390.     
  391.     gProbes--;
  392.     if (gProbes==0)
  393.         gProbing=false;
  394.     
  395.     DisposeTCPiopbPtr(tcp);
  396.     
  397.     if (err==noErr){
  398.         // Display the text...
  399.         err=ReportData(buffer,buflen,host,port);
  400.     }
  401.     
  402.     return err;
  403. }
  404.  
  405. OSErr ReportData(char* buffer,short buflen,ip_addr host,short port){
  406. #if defined(SYMANTEC_C)||defined(THINK_C)
  407.     OSErr err=noErr;
  408.     DialogPtr dlg;
  409.     Handle h;
  410.     short i,num;
  411.     Rect r;
  412.     Str255 sa[4];
  413.     register short loop=0;
  414.     Str255 hostport,temp;
  415.     long val;
  416.     
  417.     while (loop<4){
  418.         if (buflen>0){
  419.             if (buflen>255)
  420.                 num=255;
  421.             else
  422.                 num=buflen;
  423.             
  424.             // set up the string
  425.             BlockMoveData((Ptr)buffer,(Ptr)&(sa[loop][1]),num);
  426.             sa[loop][0]=num;
  427.             
  428.             // fix the pointers for the next pass
  429.             buffer+=num;
  430.             buflen-=num;
  431.         } else
  432.             sa[loop][0]=0;
  433.         loop++;
  434.     }
  435.     
  436.     hostport[0]=0;
  437.     
  438. #define AddChar(s,c) s[1+s[0]++]=c
  439.     
  440.     val=host>>24;
  441.     NumToString(val,temp);
  442.     i=0;
  443.     while (i<temp[0]){
  444.         AddChar(hostport,temp[i+1]);
  445.         i++;
  446.     }
  447.     AddChar(hostport,'.');
  448.     
  449.     
  450.     val=(host>>16)&0x000000ff;
  451.     NumToString(val,temp);
  452.     i=0;
  453.     while (i<temp[0]){
  454.         AddChar(hostport,temp[i+1]);
  455.         i++;
  456.     }
  457.     AddChar(hostport,'.');
  458.     
  459.     val=(host>>8) & 0x000000ff;
  460.     NumToString(val,temp);
  461.     i=0;
  462.     while (i<temp[0]){
  463.         AddChar(hostport,temp[i+1]);
  464.         i++;
  465.     }
  466.     AddChar(hostport,'.');
  467.     
  468.     val=host&0x000000ff;
  469.     NumToString(val,temp);
  470.     i=0;
  471.     while (i<temp[0]){
  472.         AddChar(hostport,temp[i+1]);
  473.         i++;
  474.     }
  475.     AddChar(hostport,':');
  476.     
  477.     val=port & 0x000000ff;
  478.     NumToString(val,temp);
  479.     i=0;
  480.     while (i<temp[0]){
  481.         AddChar(hostport,temp[i+1]);
  482.         i++;
  483.     }
  484.     
  485.     dlg=GetNewDialog(129,(Ptr)0L,(WindowPtr)-1);
  486.     
  487.     if (dlg!=(DialogPtr)0){
  488.         GrafPtr save;
  489.         
  490.         GetPort(&save);
  491.         
  492.         SetWRefCon((WindowPtr)dlg,'NebP');
  493.         
  494.         SetPort(dlg);
  495.         
  496.         ParamText(sa[0],sa[1],sa[2],sa[3]);
  497.         
  498.         GetDItem(dlg,4,&i,&h,&r);
  499.         SetIText(h,hostport);
  500.         
  501.         ShowWindow((WindowPtr)dlg);
  502.         
  503.         SetPort(save);
  504.     } else
  505.         err=ResError();
  506.     
  507.     return err;
  508. #else // using SIOUX & MetroWorks
  509.     printf("Data receved from %d.%d.%d.%d:%d\n",
  510.         (host>>24) & 255,
  511.         (host>>16) & 255,
  512.         (host>> 8) & 255,
  513.         (host)     & 255,
  514.         port);
  515.  
  516.     fwrite(buffer, 1, buflen, stdout);
  517.     return noErr;
  518. #endif
  519. }
  520.  
  521. OSErr HandleDataArrivals(void){
  522.     OSErr err=noErr;
  523.     short count=0;
  524.     
  525.     if (gtDataArrived){
  526.         if (tnlist>0){
  527.             SpinStart(-1);
  528.             
  529.             while (count<tnlist){
  530.                 err=HandleTCPDataStream(tlist[count]);
  531.                 
  532.                 if (err!=noErr){
  533.                     SpinStop();
  534.                     return err;
  535.                 }
  536.                 count++;
  537.             }
  538.             tnlist=0;
  539.             SpinStop();
  540.         }
  541.     }
  542.     count=0;
  543.     
  544.     if (gDataArrived){
  545.         // some data needs to be received
  546.         
  547.         if (nlist>0){
  548.             SpinStart(-1);
  549.             
  550.             while (count<nlist){
  551.                 // handle the stream pointed to by list[count]
  552.                 err=HandleDataStream(list[count]);
  553.                 
  554.                 if (err!=noErr){
  555.                     SpinStop();
  556.                     return err;
  557.                 }    
  558.                 count++;
  559.             };
  560.             
  561.             nlist=0;
  562.             SpinStop();
  563.         }
  564.     }
  565.     
  566.     return err;
  567. }
  568.  
  569. OSErr TCPProbe(ip_addr host,short port,short timeout,char* txt){
  570.     OSErr err=noErr;
  571.     TCPiopbPtr tcp;
  572.     Ptr buffer;
  573.     TCPNotifyUPP notify;
  574.     StreamPtr stream;
  575.     wdsEntry en[3];
  576.     short slen;
  577.     
  578.     tcp=NewTCPiopbPtr();
  579.     buffer=NewPtr(10*1024);
  580.     
  581.     notify=NewTCPNotifyProc(TCPNotify);
  582.     
  583.     tcp->ioCRefNum=gMacTCP;
  584.     tcp->csParam.create.rcvBuff=buffer;
  585.     tcp->csParam.create.rcvBuffLen=10*1024;
  586.     tcp->csParam.create.notifyProc=notify;
  587.     
  588.     err=TCP_Create(tcp,false); // create the stream...
  589.     
  590.     if (err==noErr){
  591.         // then the stream was created...
  592.         stream=tcp->tcpStream;
  593.         tactive[taque]=stream;
  594.         thosts[taque]=host;
  595.         tports[taque++]=port;
  596.         
  597.         if (taque==200)
  598.             taque=0;
  599.         
  600.         // now send the data on the stream...
  601.         slen=StrLen(txt);
  602.         
  603.         en[0].length=slen;
  604.         en[0].ptr=txt;
  605.         
  606.         en[1].length=0;
  607.         en[1].ptr=0;
  608.         
  609.         // now open the connection...
  610.         tcp->ioCRefNum=gMacTCP;
  611.         tcp->ioCompletion=0L;
  612.         tcp->tcpStream=stream;
  613.         tcp->csParam.open.ulpTimeoutValue=0;
  614.         tcp->csParam.open.ulpTimeoutAction=0;
  615.         tcp->csParam.open.remoteHost=host;
  616.         tcp->csParam.open.remotePort=port;
  617.         tcp->csParam.open.validityFlags=0;
  618.         tcp->csParam.open.tosFlags=0;
  619.         tcp->csParam.open.precedence=0;
  620.         tcp->csParam.open.dontFrag=true;
  621.         tcp->csParam.open.timeToLive=0;
  622.         tcp->csParam.open.security=0;
  623.         tcp->csParam.open.optionCnt=0;
  624.         
  625.         err=TCP_ActiveOpen(tcp,false);
  626.         
  627.         if ((err==noErr)&&(slen>0)){
  628.             // then the connection has been opened, send the text....
  629.             
  630.             // refill tcp
  631.             
  632.             tcp->ioCompletion=0L;
  633.             tcp->ioCRefNum=gMacTCP;
  634.             tcp->tcpStream=stream;
  635.             tcp->csParam.send.ulpTimeoutValue=0;
  636.             tcp->csParam.send.ulpTimeoutAction=0;
  637.             tcp->csParam.send.validityFlags=0;
  638.             tcp->csParam.send.pushFlag=true;
  639.             tcp->csParam.send.urgentFlag=false;
  640.             tcp->csParam.send.wdsPtr=(char*)en;
  641.             
  642.             err=TCP_Send(tcp,false); // do it synchronously...
  643.             
  644.             if (err==noErr){
  645.                 
  646.                 if (tcp->ioResult==noErr){
  647.                     // no Errors
  648.                 } else
  649.                     err=tcp->ioResult;
  650.             }
  651.         }
  652.     }
  653.     
  654.     // everything should have been sent already
  655.     // ok to return...
  656.     
  657.     DisposeTCPiopbPtr(tcp);
  658.     
  659.     gProbing=true;
  660.     gProbes++;
  661.     
  662.     return err;
  663. }
  664.  
  665. OSErr Probe(ip_addr host,short port,short timeout,char* txt){
  666.     OSErr err=noErr;
  667.     UDPiopbPtr udp;
  668.     Ptr buffer;
  669.     UDPNotifyUPP notify;
  670.     StreamPtr stream;
  671.     wdsEntry en[3];
  672.     
  673.     udp=NewUDPiopbPtr();
  674.     buffer=NewPtr(10*1024);// allocate a receive buffer
  675.     
  676.     notify=NewUDPNotifyProc(UDPNotify);
  677.     
  678.     udp->ioCRefNum=gMacTCP;
  679.     udp->csParam.create.rcvBuff=buffer;
  680.     udp->csParam.create.rcvBuffLen=10*1024;
  681.     udp->csParam.create.localPort=port;
  682.     udp->csParam.create.notifyProc=notify;
  683.     udp->csParam.create.userDataPtr=(Ptr)SetCurrentA5();
  684.     
  685.     err=UDP_Create(udp,false); // do it synchronously...
  686.     
  687.     if (err==noErr){
  688.         // then the stream was created...
  689.         stream=udp->udpStream;
  690.         active[aque++]=udp->udpStream;
  691.         if (aque==200)
  692.             aque=0;
  693.         
  694.         // now send the data on the stream...
  695.         
  696.         en[0].length=StrLen(txt);
  697.         en[0].ptr=txt;
  698.         
  699.         en[1].length=0;
  700.         en[1].ptr=0;
  701.         
  702.         // refill udp
  703.         
  704.         udp->ioCompletion=0L;
  705.         udp->ioCRefNum=gMacTCP;
  706.         udp->csParam.send.reserved=0;
  707.         udp->csParam.send.remoteHost=host;
  708.         udp->csParam.send.remotePort=port;
  709.         udp->csParam.send.checkSum=true;
  710.         udp->csParam.send.wdsPtr=(char*)en;
  711.         udp->csParam.send.localPort=port;
  712.         
  713.         err=UDP_Write(udp,false); // do it synchronously...
  714.         
  715.         if (err==noErr){
  716.             
  717.             if (udp->ioResult==noErr){
  718.                 // then the packet was sent successfully...
  719.             } else
  720.                 err=udp->ioResult;
  721.         }
  722.         
  723.     }
  724.     
  725.     // everything should have been sent already
  726.     // ok to return...
  727.     DisposeUDPiopbPtr(udp);
  728.     
  729.     gProbing=true;
  730.     gProbes++;
  731.     
  732.     return err;
  733. }
  734.  
  735. OSErr StopProbe(void){
  736.     OSErr err=noErr;
  737.     register short loop=0;
  738.     UDPiopbPtr udp;
  739.     
  740.     udp=NewUDPiopbPtr();
  741.     
  742.     while (loop<200){
  743.         if (active[loop]!=(StreamPtr)-1){
  744.             udp->ioCRefNum=gMacTCP;
  745.             udp->udpStream=active[loop];
  746.             
  747.             err=UDP_Release(udp,false);
  748.         }
  749.         loop++;
  750.     }
  751.     
  752.     DisposeUDPiopbPtr(udp);
  753.     
  754.     return err;
  755. }
  756.  
  757.