@@ -30,8 +30,21 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3030
3131#include <Desk.h>
3232
33+ /* State of a tcp stream, in the connectionState field */
34+ #define STATE_CLOSED 0
35+ #define STATE_LISTEN 2
36+ #define STATE_ESTAB 8
37+ #define STATE_CWAIT 18
38+
3339static object * ErrorObject ;
3440
41+ TCPIOCompletionUPP upp_tcp_done ;
42+ TCPNotifyUPP upp_tcp_asr ;
43+ #if 0
44+ UDPIOCompletionUPP upp_udp_done ;
45+ #endif
46+ UDPNotifyUPP upp_udp_asr ;
47+
3548/* ----------------------------------------------------- */
3649/* Declarations for objects of type MacTCP connection status */
3750
@@ -64,6 +77,8 @@ staticforward typeobject Tcpgstype;
6477typedef struct {
6578 OB_HEAD
6679 TCPiopb iop ;
80+ long localhost ; /* Our IP address */
81+ short localport ; /* Our port number */
6782 object * asr ; /* Optional async notification routine */
6883 int asr_ec ; /* error code parameter to asr */
6984 int asr_reason ; /* detail for some errors */
@@ -241,6 +256,34 @@ static typeobject Tcpgstype = {
241256/* End of code for MacTCP global status objects */
242257/* -------------------------------------------------------- */
243258
259+ static int
260+ tcps_checkstate (self , state , state2 )
261+ tcpsobject * self ;
262+ int state , state2 ;
263+ {
264+ OSErr err ;
265+ TCPStatusPB * pb ;
266+ char buf [80 ];
267+
268+ if ( self -> async_busy ) {
269+ err_setstr (ErrorObject , "Operation not allowed, PassiveOpen in progress" );
270+ return -1 ;
271+ }
272+ if ( state < 0 && state2 < 0 )
273+ return 0 ;
274+ err = xTCPStatus (& self -> iop , & pb );
275+ if ( err ) {
276+ PyErr_Mac (ErrorObject , err );
277+ return -1 ;
278+ }
279+ if ( state == pb -> connectionState ||
280+ state2 == pb -> connectionState )
281+ return 0 ;
282+ sprintf (buf , "Operation not allowed, connection state=%d" , pb -> connectionState );
283+ err_setstr (ErrorObject , buf );
284+ return -1 ;
285+ }
286+
244287static int
245288tcps_asr_safe (arg )
246289 void * arg ;
@@ -276,14 +319,14 @@ tcps_asr(str, ec, self, reason, icmp)
276319}
277320
278321static void
279- tcps_opendone (pb )
322+ tcps_done (pb )
280323 TCPiopb * pb ;
281324{
282325 tcpsobject * self = (tcpsobject * )pb -> csParam .open .userDataPtr ;
283326
284327 if ( pb != & self -> iop || !self -> async_busy ) {
285328 /* Oops... problems */
286- printf ("tcps_opendone : unexpected call\n" );
329+ printf ("tcps_done : unexpected call\n" );
287330 return ;
288331 }
289332 self -> async_busy = 0 ;
@@ -339,15 +382,19 @@ tcps_PassiveOpen(self, args)
339382
340383 if (!newgetargs (args , "h" , & port ))
341384 return NULL ;
385+ if ( tcps_checkstate (self , -1 , -1 ) < 0 )
386+ return NULL ;
342387 self -> async_busy = 1 ;
343388 self -> async_err = 0 ;
344- err = xTCPPassiveOpen (& self -> iop , port , ( TCPIOCompletionProc ) tcps_opendone ,
389+ err = xTCPPassiveOpen (& self -> iop , port , upp_tcp_done ,
345390 (void * )self );
346391 if ( err ) {
347392 self -> async_busy = 0 ;
348393 PyErr_Mac (ErrorObject , err );
349394 return NULL ;
350395 }
396+ self -> localhost = self -> iop .csParam .open .localHost ;
397+ self -> localport = self -> iop .csParam .open .localPort ;
351398 INCREF (None );
352399 return None ;
353400}
@@ -363,11 +410,15 @@ tcps_ActiveOpen(self, args)
363410
364411 if (!newgetargs (args , "hlh" , & lport , & rhost , & rport ))
365412 return NULL ;
366- err = xTCPActiveOpen (& self -> iop , lport , rhost , rport , (TCPIOCompletionProc )0 );
413+ if ( tcps_checkstate (self , -1 , -1 ) < 0 )
414+ return NULL ;
415+ err = xTCPActiveOpen (& self -> iop , lport , rhost , rport , (TCPIOCompletionUPP )0 );
367416 if ( err ) {
368417 PyErr_Mac (ErrorObject , err );
369418 return NULL ;
370419 }
420+ self -> localhost = self -> iop .csParam .open .localHost ;
421+ self -> localport = self -> iop .csParam .open .localPort ;
371422 INCREF (None );
372423 return None ;
373424}
@@ -385,11 +436,13 @@ tcps_Send(self, args)
385436
386437 if (!newgetargs (args , "s#|ii" , & buf , & bufsize , & push , & urgent ))
387438 return NULL ;
439+ if ( tcps_checkstate (self , STATE_ESTAB , STATE_CWAIT ) < 0 )
440+ return NULL ;
388441 wds .length = bufsize ;
389442 wds .ptr = buf ;
390443 wds .terminus = 0 ;
391444 err = xTCPSend (& self -> iop , (wdsEntry * )& wds , (Boolean )push , (Boolean )urgent ,
392- (TCPIOCompletionProc )0 );
445+ (TCPIOCompletionUPP )0 );
393446 if ( err ) {
394447 PyErr_Mac (ErrorObject , err );
395448 return NULL ;
@@ -412,16 +465,18 @@ tcps_Rcv(self, args)
412465
413466 if (!newgetargs (args , "i" , & timeout ))
414467 return NULL ;
468+ if ( tcps_checkstate (self , -1 , -1 ) < 0 )
469+ return NULL ;
415470 memset ((char * )& rds , 0 , sizeof (rds ));
416- err = xTCPNoCopyRcv (& self -> iop , rds , 1 , timeout , (TCPIOCompletionProc )0 );
471+ err = xTCPNoCopyRcv (& self -> iop , rds , 1 , timeout , (TCPIOCompletionUPP )0 );
417472 if ( err ) {
418473 PyErr_Mac (ErrorObject , err );
419474 return NULL ;
420475 }
421476 urgent = self -> iop .csParam .receive .urgentFlag ;
422477 mark = self -> iop .csParam .receive .markFlag ;
423478 rv = newsizedstringobject ((char * )rds [0 ].ptr , rds [0 ].length );
424- err = xTCPBufReturn (& self -> iop , rds , (TCPIOCompletionProc )0 );
479+ err = xTCPBufReturn (& self -> iop , rds , (TCPIOCompletionUPP )0 );
425480 if ( err ) {
426481 /* Should not happen */ printf ("mactcp module: BufReturn failed?\n" );
427482 PyErr_Mac (ErrorObject , err );
@@ -440,7 +495,7 @@ tcps_Close(self, args)
440495
441496 if (!newgetargs (args , "" ))
442497 return NULL ;
443- err = xTCPClose (& self -> iop , (TCPIOCompletionProc )0 );
498+ err = xTCPClose (& self -> iop , (TCPIOCompletionUPP )0 );
444499 if ( err ) {
445500 PyErr_Mac (ErrorObject , err );
446501 return NULL ;
@@ -477,6 +532,8 @@ tcps_Status(self, args)
477532
478533 if (!newgetargs (args , "" ))
479534 return NULL ;
535+ if ( tcps_checkstate (self , -1 , -1 ) < 0 )
536+ return NULL ;
480537 err = xTCPStatus (& self -> iop , & pb );
481538 if ( err ) {
482539 PyErr_Mac (ErrorObject , err );
@@ -485,6 +542,21 @@ tcps_Status(self, args)
485542 return (object * )newtcpcsobject (pb );
486543}
487544
545+ static object *
546+ tcps_GetSockName (self , args )
547+ tcpsobject * self ;
548+ object * args ;
549+ {
550+ /* This routine is needed so we can get at the local port even when
551+ ** a PassiveOpen is in progress (when we can't do a Status call).
552+ ** This is needed for socket listen(); getsockname(); accept() emulation
553+ ** as used by ftp and the like.
554+ */
555+ if (!newgetargs (args , "" ))
556+ return NULL ;
557+ return mkvalue ("(lh)" , self -> localhost , self -> localport );
558+ }
559+
488560static struct methodlist tcps_methods [] = {
489561 {"isdone" , (method )tcps_isdone , 1 },
490562 {"wait" , (method )tcps_wait , 1 },
@@ -495,6 +567,7 @@ static struct methodlist tcps_methods[] = {
495567 {"Close" , (method )tcps_Close , 1 },
496568 {"Abort" , (method )tcps_Abort , 1 },
497569 {"Status" , (method )tcps_Status , 1 },
570+ {"GetSockName" , (method )tcps_GetSockName , 1 },
498571 {NULL , NULL } /* sentinel */
499572};
500573
@@ -535,7 +608,7 @@ newtcpsobject(bufsize)
535608 if (self == NULL )
536609 return NULL ;
537610 memset ((char * )& self -> iop , 0 , sizeof (self -> iop ));
538- err = xTCPCreate (bufsize , ( TCPNotifyProc ) tcps_asr , (void * )self , & self -> iop );
611+ err = xTCPCreate (bufsize , upp_tcp_asr , (void * )self , & self -> iop );
539612 if ( err ) {
540613 DEL (self );
541614 PyErr_Mac (ErrorObject , err );
@@ -626,7 +699,7 @@ udps_Read(self, args)
626699
627700 if (!newgetargs (args , "i" , & timeout ))
628701 return NULL ;
629- err = xUDPRead (& self -> iop , timeout , (UDPIOCompletionProc )0 );
702+ err = xUDPRead (& self -> iop , timeout , (UDPIOCompletionUPP )0 );
630703 if ( err ) {
631704 PyErr_Mac (ErrorObject , err );
632705 return NULL ;
@@ -659,7 +732,7 @@ udps_Write(self, args)
659732 wds .length = bufsize ;
660733 wds .ptr = buf ;
661734 wds .terminus = 0 ;
662- err = xUDPWrite (& self -> iop , host , port , & wds , (UDPIOCompletionProc )0 );
735+ err = xUDPWrite (& self -> iop , host , port , & wds , (UDPIOCompletionUPP )0 );
663736 if ( err ) {
664737 PyErr_Mac (ErrorObject , err );
665738 return NULL ;
@@ -715,7 +788,7 @@ newudpsobject(bufsize, port)
715788 return NULL ;
716789 memset ((char * )& self -> iop , 0 , sizeof (self -> iop ));
717790 self -> port = port ;
718- err = xUDPCreate (& self -> iop , bufsize , & self -> port , ( UDPNotifyProc ) udps_asr ,
791+ err = xUDPCreate (& self -> iop , bufsize , & self -> port , upp_udp_asr ,
719792 (void * )self );
720793 if ( err ) {
721794 DEL (self );
@@ -899,6 +972,13 @@ initmactcp()
899972 d = getmoduledict (m );
900973 ErrorObject = newstringobject ("mactcp.error" );
901974 dictinsert (d , "error" , ErrorObject );
975+
976+ upp_tcp_done = NewTCPIOCompletionProc (tcps_done );
977+ upp_tcp_asr = NewTCPNotifyProc (tcps_asr );
978+ #if 0
979+ upp_udp_done = NewUDPIOCompletionProc (udps_done );
980+ #endif
981+ upp_udp_asr = NewUDPNotifyProc (udps_asr );
902982
903983 /* XXXX Add constants here */
904984
0 commit comments