@@ -69,7 +69,6 @@ type Client struct {
69
69
closed bool
70
70
71
71
routerGoodbye * wamp.Goodbye
72
- idGen * wamp.SyncIDGen
73
72
}
74
73
75
74
// InvokeResult represents the result of invoking a procedure.
@@ -256,7 +255,6 @@ func NewClient(p wamp.Peer, cfg Config) (*Client, error) {
256
255
log : cfg .Logger ,
257
256
debug : cfg .Debug ,
258
257
cancelMode : wamp .CancelModeKillNoWait ,
259
- idGen : new (wamp.SyncIDGen ),
260
258
}
261
259
c .ctx , c .cancel = context .WithCancel (context .Background ())
262
260
go c .run () // start the core goroutine
@@ -313,7 +311,7 @@ func (c *Client) Subscribe(topic string, fn EventHandler, options wamp.Dict) err
313
311
if options == nil {
314
312
options = wamp.Dict {}
315
313
}
316
- id := c .idGen .Next ()
314
+ id := c .sess . IdGen .Next ()
317
315
c .expectReply (id )
318
316
c .sess .Send () <- & wamp.Subscribe {
319
317
Request : id ,
@@ -384,7 +382,7 @@ func (c *Client) Unsubscribe(topic string) error {
384
382
return ErrNotConn
385
383
}
386
384
387
- id := c .idGen .Next ()
385
+ id := c .sess . IdGen .Next ()
388
386
c .expectReply (id )
389
387
c .sess .Send () <- & wamp.Unsubscribe {
390
388
Request : id ,
@@ -453,7 +451,7 @@ func (c *Client) Publish(topic string, options wamp.Dict, args wamp.List, kwargs
453
451
return ErrNotConn
454
452
}
455
453
456
- id := c .idGen .Next ()
454
+ id := c .sess . IdGen .Next ()
457
455
458
456
var pubAck bool
459
457
if options == nil {
@@ -570,7 +568,7 @@ func (c *Client) Register(procedure string, fn InvocationHandler, options wamp.D
570
568
if ! c .Connected () {
571
569
return ErrNotConn
572
570
}
573
- id := c .idGen .Next ()
571
+ id := c .sess . IdGen .Next ()
574
572
c .expectReply (id )
575
573
if options == nil {
576
574
options = wamp.Dict {}
@@ -636,7 +634,7 @@ func (c *Client) Unregister(procedure string) error {
636
634
return ErrNotConn
637
635
}
638
636
639
- id := c .idGen .Next ()
637
+ id := c .sess . IdGen .Next ()
640
638
c .expectReply (id )
641
639
c .sess .Send () <- & wamp.Unregister {
642
640
Request : id ,
@@ -758,7 +756,7 @@ func (c *Client) Call(ctx context.Context, procedure string, options wamp.Dict,
758
756
}()
759
757
}
760
758
761
- id := c .idGen .Next ()
759
+ id := c .sess . IdGen .Next ()
762
760
c .expectReply (id )
763
761
message := & wamp.Call {
764
762
Request : id ,
@@ -857,7 +855,7 @@ func (c *Client) CallProgressive(ctx context.Context, procedure string, sendProg
857
855
}()
858
856
}
859
857
860
- id := c .idGen .Next ()
858
+ id := c .sess . IdGen .Next ()
861
859
c .expectReply (id )
862
860
message := & wamp.Call {
863
861
Request : id ,
@@ -1445,14 +1443,17 @@ func (c *Client) runReceiveFromRouter(msg wamp.Message) bool {
1445
1443
if c .debug {
1446
1444
c .log .Println ("Client" , c .sess , "received" , msg .MessageType ())
1447
1445
}
1446
+
1448
1447
switch msg := msg .(type ) {
1449
1448
case * wamp.Event :
1450
1449
c .runHandleEvent (msg )
1451
1450
1452
1451
case * wamp.Invocation :
1453
1452
c .runHandleInvocation (msg )
1453
+ c .sess .UpdateLastRecvID (msg .Request )
1454
1454
case * wamp.Interrupt :
1455
1455
c .runHandleInterrupt (msg )
1456
+ c .sess .UpdateLastRecvID (msg .Request )
1456
1457
1457
1458
case * wamp.Registered :
1458
1459
c .runSignalReply (msg , msg .Request )
@@ -1535,6 +1536,38 @@ func (c *Client) runHandleEvent(msg *wamp.Event) {
1535
1536
handler (msg )
1536
1537
}
1537
1538
1539
+ func (c * Client ) cleanupInvHandlersQueue (cliInvocation clientInvocation ) {
1540
+ c .sess .Lock ()
1541
+ defer c .sess .Unlock ()
1542
+
1543
+ handlerQueue , _ := c .invHandlersQueues [cliInvocation ]
1544
+ delete (c .invHandlersQueues , cliInvocation )
1545
+ delete (c .invHandlersCtxs , cliInvocation )
1546
+
1547
+ if nil == handlerQueue {
1548
+ return
1549
+ }
1550
+ if c .debug {
1551
+ c .log .Println ("Running cleanupInvHandlersQueue cleanup for" , cliInvocation )
1552
+ }
1553
+
1554
+ // Try to get any remaining values off the chan (in case anyone is blocked)
1555
+ for {
1556
+ select {
1557
+ case msg := <- handlerQueue :
1558
+ if nil == msg {
1559
+ return // chan closed
1560
+ }
1561
+ continue
1562
+ default :
1563
+ return
1564
+ }
1565
+ }
1566
+ // Don't bother closing in the very rare event that someone still has
1567
+ // a reference and tries to send
1568
+ // close(c.invHandlersQueues[cliInvocation])
1569
+ }
1570
+
1538
1571
// runHandleInvocation processes an INVOCATION message from the router
1539
1572
// requesting a call to a registered RPC procedure.
1540
1573
func (c * Client ) runHandleInvocation (msg * wamp.Invocation ) {
@@ -1616,6 +1649,19 @@ func (c *Client) runHandleInvocation(msg *wamp.Invocation) {
1616
1649
handlerQueue , queueExists := c .invHandlersQueues [cliInvocation ]
1617
1650
ctx := c .invHandlersCtxs [cliInvocation ]
1618
1651
if ! queueExists {
1652
+ // Only create the queue if this is a new request
1653
+ if ! c .sess .UpdateLastRecvIDCallerHasSessionLock (reqID ) {
1654
+ c .sess .Unlock ()
1655
+ if c .debug {
1656
+ c .log .Println ("Ignoring Invocation with expired reqID=" , reqID )
1657
+ }
1658
+ // discard silently
1659
+ return
1660
+ }
1661
+
1662
+ if c .debug {
1663
+ c .log .Println ("Creating new handlerQueue reqID=" , reqID )
1664
+ }
1619
1665
handlerQueue = make (chan * wamp.Invocation , 1 )
1620
1666
c .invHandlersQueues [cliInvocation ] = handlerQueue
1621
1667
@@ -1638,7 +1684,6 @@ func (c *Client) runHandleInvocation(msg *wamp.Invocation) {
1638
1684
ctx = context .WithValue (ctx , invocationIDCtxKey {}, reqID )
1639
1685
}
1640
1686
}
1641
-
1642
1687
c .sess .Unlock ()
1643
1688
1644
1689
handlerQueue <- msg
@@ -1652,21 +1697,36 @@ func (c *Client) runHandleInvocation(msg *wamp.Invocation) {
1652
1697
// Otherwise, canceling the call will leak the goroutine that is
1653
1698
// blocked forever waiting to send the result to the channel.
1654
1699
resChan := make (chan InvokeResult , 1 )
1700
+
1701
+ // Start goroutine to process inbound Invocation messages
1655
1702
go func () {
1656
- for msg := range handlerQueue {
1657
-
1658
- if isInProgress , _ := msg .Details [wamp .OptProgress ].(bool ); ! isInProgress {
1659
- c .sess .Lock ()
1660
- close (c .invHandlersQueues [cliInvocation ])
1661
- delete (c .invHandlersQueues , cliInvocation )
1662
- delete (c .invHandlersCtxs , cliInvocation )
1663
- c .sess .Unlock ()
1664
- }
1703
+ defer c .cleanupInvHandlersQueue (cliInvocation )
1704
+
1705
+ processMessages := true
1706
+ for processMessages {
1707
+ select {
1708
+ case msg := <- handlerQueue :
1709
+ if msg == nil { // chan closed
1710
+ return
1711
+ }
1712
+ if isInProgress , _ := msg .Details [wamp .OptProgress ].(bool ); ! isInProgress {
1713
+ c .cleanupInvHandlersQueue (cliInvocation )
1714
+ processMessages = false
1715
+ }
1665
1716
1666
- // The Context is passed into the handler to tell the client
1667
- // application to stop whatever it is doing if it cares to pay
1668
- // attention.
1669
- resChan <- handler (ctx , msg )
1717
+ // The Context is passed into the handler to tell the client
1718
+ // application to stop whatever it is doing if it cares to pay
1719
+ // attention.
1720
+ result := handler (ctx , msg )
1721
+ resChan <- result
1722
+ if result .Err != "" && result .Err != wamp .InternalProgressiveOmitResult {
1723
+ processMessages = false
1724
+ }
1725
+ case <- c .Done ():
1726
+ return
1727
+ case <- ctx .Done ():
1728
+ return
1729
+ }
1670
1730
}
1671
1731
}()
1672
1732
0 commit comments