diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Network/BitTorrent/Tracker/RPC/UDP.hs | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/src/Network/BitTorrent/Tracker/RPC/UDP.hs b/src/Network/BitTorrent/Tracker/RPC/UDP.hs index 15701062..0e592398 100644 --- a/src/Network/BitTorrent/Tracker/RPC/UDP.hs +++ b/src/Network/BitTorrent/Tracker/RPC/UDP.hs | |||
@@ -93,14 +93,16 @@ instance Default Options where | |||
93 | -- Manager state | 93 | -- Manager state |
94 | -----------------------------------------------------------------------} | 94 | -----------------------------------------------------------------------} |
95 | 95 | ||
96 | type ConnectionCache = Map SockAddr Connection | ||
96 | type PendingTransactions = Map TransactionId (MVar Response) | 97 | type PendingTransactions = Map TransactionId (MVar Response) |
98 | type PendingQueries = Map SockAddr PendingTransactions | ||
97 | 99 | ||
98 | data Manager = Manager | 100 | data Manager = Manager |
99 | { options :: !Options | 101 | { options :: !Options |
100 | , sock :: !Socket | 102 | , sock :: !Socket |
101 | -- , dnsCache :: !(IORef (Map URI SockAddr)) | 103 | -- , dnsCache :: !(IORef (Map URI SockAddr)) |
102 | , connectionCache :: !(IORef (Map SockAddr Connection)) | 104 | , connectionCache :: !(IORef ConnectionCache) |
103 | , pendingResps :: !(MVar (Map SockAddr PendingTransactions)) | 105 | , pendingResps :: !(MVar PendingQueries) |
104 | , listenerThread :: !(MVar ThreadId) | 106 | , listenerThread :: !(MVar ThreadId) |
105 | } | 107 | } |
106 | 108 | ||
@@ -363,6 +365,23 @@ isExpired Connection {..} = do | |||
363 | -- Transactions | 365 | -- Transactions |
364 | -----------------------------------------------------------------------} | 366 | -----------------------------------------------------------------------} |
365 | 367 | ||
368 | register :: SockAddr -> TransactionId -> MVar Response | ||
369 | -> PendingQueries -> PendingQueries | ||
370 | register addr tid ares = M.alter insertId addr | ||
371 | where | ||
372 | insertId Nothing = Just (M.singleton tid ares) | ||
373 | insertId (Just m) = Just (M.insert tid ares m) | ||
374 | |||
375 | unregister :: SockAddr -> TransactionId | ||
376 | -> PendingQueries -> PendingQueries | ||
377 | unregister addr tid = M.update deleteId addr | ||
378 | where | ||
379 | deleteId m | ||
380 | | M.null m' = Nothing | ||
381 | | otherwise = Just m' | ||
382 | where | ||
383 | m' = M.delete tid m | ||
384 | |||
366 | -- | Generate a new unused transaction id. | 385 | -- | Generate a new unused transaction id. |
367 | allocTransaction :: Manager -> SockAddr -> MVar Response -> IO TransactionId | 386 | allocTransaction :: Manager -> SockAddr -> MVar Response -> IO TransactionId |
368 | allocTransaction Manager {..} addr ares = modifyMVar pendingResps bindId | 387 | allocTransaction Manager {..} addr ares = modifyMVar pendingResps bindId |
@@ -371,10 +390,7 @@ allocTransaction Manager {..} addr ares = modifyMVar pendingResps bindId | |||
371 | tid <- genTransactionId | 390 | tid <- genTransactionId |
372 | case M.lookup tid =<< M.lookup addr m of | 391 | case M.lookup tid =<< M.lookup addr m of |
373 | Just _ -> bindId m -- already used, retry | 392 | Just _ -> bindId m -- already used, retry |
374 | Nothing -> return (M.alter (insertId tid) addr m, tid) | 393 | Nothing -> return (register addr tid ares m, tid) |
375 | |||
376 | insertId tid Nothing = Just (M.singleton tid ares) | ||
377 | insertId tid (Just m) = Just (M.insert tid ares m) | ||
378 | 394 | ||
379 | -- | Wake up blocked thread and return response back. | 395 | -- | Wake up blocked thread and return response back. |
380 | commitTransaction :: Manager -> SockAddr -> TransactionId -> Response -> IO () | 396 | commitTransaction :: Manager -> SockAddr -> TransactionId -> Response -> IO () |
@@ -384,25 +400,13 @@ commitTransaction Manager {..} addr tid resp = | |||
384 | Nothing -> return m -- tracker responded after 'cancelTransaction' fired | 400 | Nothing -> return m -- tracker responded after 'cancelTransaction' fired |
385 | Just ares -> do | 401 | Just ares -> do |
386 | putMVar ares resp | 402 | putMVar ares resp |
387 | return $ M.update deleteId addr m | 403 | return $ unregister addr tid m |
388 | where | ||
389 | deleteId m | ||
390 | | M.null m' = Nothing | ||
391 | | otherwise = Just m' | ||
392 | where | ||
393 | m' = M.delete tid m | ||
394 | 404 | ||
395 | -- | Abort transaction forcefully. | 405 | -- | Abort transaction forcefully. |
396 | cancelTransaction :: Manager -> SockAddr -> TransactionId -> IO () | 406 | cancelTransaction :: Manager -> SockAddr -> TransactionId -> IO () |
397 | cancelTransaction Manager {..} addr tid = | 407 | cancelTransaction Manager {..} addr tid = |
398 | modifyMVarMasked_ pendingResps $ \m -> | 408 | modifyMVarMasked_ pendingResps $ \m -> |
399 | return $ M.update deleteId addr m | 409 | return $ unregister addr tid m |
400 | where | ||
401 | deleteId m | ||
402 | | M.null m' = Nothing | ||
403 | | otherwise = Just m' | ||
404 | where | ||
405 | m' = M.delete tid m | ||
406 | 410 | ||
407 | -- | Handle responses from trackers. | 411 | -- | Handle responses from trackers. |
408 | listen :: Manager -> IO () | 412 | listen :: Manager -> IO () |