summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Presence/Server.hs61
-rw-r--r--test-server.hs541
2 files changed, 591 insertions, 11 deletions
diff --git a/Presence/Server.hs b/Presence/Server.hs
index 4cbaaa7d..5e54ff27 100644
--- a/Presence/Server.hs
+++ b/Presence/Server.hs
@@ -3,6 +3,9 @@
3{-# LANGUAGE StandaloneDeriving #-} 3{-# LANGUAGE StandaloneDeriving #-}
4{-# LANGUAGE OverloadedStrings #-} 4{-# LANGUAGE OverloadedStrings #-}
5{-# LANGUAGE TupleSections #-} 5{-# LANGUAGE TupleSections #-}
6#ifdef TEST
7{-# LANGUAGE FlexibleInstances #-}
8#endif
6----------------------------------------------------------------------------- 9-----------------------------------------------------------------------------
7-- | 10-- |
8-- Module : Server 11-- Module : Server
@@ -57,6 +60,9 @@ import Network.BSD
57 ( getProtocolNumber 60 ( getProtocolNumber
58 ) 61 )
59import Debug.Trace 62import Debug.Trace
63import Data.Time.Clock (UTCTime,getCurrentTime)
64import Data.Time.Format (formatTime)
65import System.Locale (defaultTimeLocale)
60 66
61todo = error "unimplemented" 67todo = error "unimplemented"
62 68
@@ -154,10 +160,15 @@ data ConnectionEvent b
154 | RequiresPing 160 | RequiresPing
155 -- ^ 'pingInterval' miliseconds of idle was experienced 161 -- ^ 'pingInterval' miliseconds of idle was experienced
156 162
157{- 163#ifdef TEST
164instance Show (IO a) where show _ = "<IO action>"
165instance Show (STM a) where show _ = "<STM action>"
166instance Eq (ByteString -> IO Bool) where (==) _ _ = True
167instance Eq (IO (Maybe ByteString)) where (==) _ _ = True
168instance Eq (STM Bool) where (==) _ _ = True
158deriving instance Show b => Show (ConnectionEvent b) 169deriving instance Show b => Show (ConnectionEvent b)
159deriving instance Eq b => Eq (ConnectionEvent b) 170deriving instance Eq b => Eq (ConnectionEvent b)
160-} 171#endif
161 172
162-- | This object accepts commands and signals events and maintains 173-- | This object accepts commands and signals events and maintains
163-- the list of currently listening ports and established connections. 174-- the list of currently listening ports and established connections.
@@ -267,7 +278,7 @@ server = do
267 doit server (Connect addr params) = liftIO $ do 278 doit server (Connect addr params) = liftIO $ do
268 void . forkIO $ do 279 void . forkIO $ do
269 proto <- getProtocolNumber "tcp" 280 proto <- getProtocolNumber "tcp"
270 sock <- bracketOnError 281 bracketOnError
271 (socket (socketFamily addr) Stream proto) 282 (socket (socketFamily addr) Stream proto)
272 (\sock -> do -- only done if there's an error 283 (\sock -> do -- only done if there's an error
273 -- Weird hack: puting the would-be peer address 284 -- Weird hack: puting the would-be peer address
@@ -277,8 +288,8 @@ server = do
277 atomically 288 atomically
278 $ writeTChan (serverEvent server) 289 $ writeTChan (serverEvent server)
279 $ (conkey,ConnectFailure addr)) 290 $ (conkey,ConnectFailure addr))
280 $ \sock -> do connect sock addr 291 $ \sock -> do
281 return sock 292 connect sock addr
282 me <- getSocketName sock 293 me <- getSocketName sock
283 conkey <- makeConnKey params (sock,me) 294 conkey <- makeConnKey params (sock,me)
284 h <- socketToHandle sock ReadWriteMode 295 h <- socketToHandle sock ReadWriteMode
@@ -370,21 +381,22 @@ newConnection server params conkey h inout = do
370 kont <- updateConMap conkey new what 381 kont <- updateConMap conkey new what
371 putTMVar started () 382 putTMVar started ()
372 return kont 383 return kont
373 {- 384#ifdef TEST
374 -- enable this for 'Got' events 385 -- enable this for 'Got' events
375 forkIO $ do -- inout==In || duplex params then forkIO $ do 386 forkIO $ do -- inout==In || duplex params then forkIO $ do
376 -- warn $ "waiting read thread: " <> bshow (conkey,inout) 387 warn $ "waiting gots thread: " <> bshow (conkey,inout)
377 atomically $ takeTMVar started 388 atomically $ takeTMVar started
378 -- pingBump pinglogic -- start the ping timer 389 -- pingBump pinglogic -- start the ping timer
379 fix $ \loop -> do 390 fix $ \loop -> do
380 -- warn $ "read thread: " <> bshow (conkey,inout) 391 -- warn $ "read thread: " <> bshow (conkey,inout)
381 mb <- threadsRead new 392 mb <- threadsRead new
382 -- pingBump pinglogic 393 -- pingBump pinglogic
383 -- warn $ "got: " <> bshow (mb,(conkey,inout)) 394 warn $ "got: " <> bshow (mb,(conkey,inout))
384 maybe (return ()) 395 maybe (return ())
385 (atomically . forward >=> const loop) 396 (atomically . forward >=> const loop)
386 mb 397 mb
387 -} 398 warn $ "quit-gots: " <> bshow (conkey,inout)
399#endif
388 return () 400 return ()
389 where 401 where
390 402
@@ -408,9 +420,23 @@ newConnection server params conkey h inout = do
408 $ Map.delete conkey 420 $ Map.delete conkey
409 -- warn $ "fin-EOF "<>bshow conkey 421 -- warn $ "fin-EOF "<>bshow conkey
410 422
411 sendPing PingTimeOut = do atomically (connClose newCon) 423 sendPing PingTimeOut = do
412 eof 424 {-
425 let me = connPingTimer newCon
426 utc <- getCurrentTime
427 let utc' = formatTime defaultTimeLocale "%s" utc
428 warn $ "TIMEOUT " <> bshow utc' <> " " <> bshow (pingIdle me, pingTimeOut me)
429 -}
430 atomically (connClose newCon)
431 eof
432
413 sendPing PingIdle = do 433 sendPing PingIdle = do
434 {-
435 let me = connPingTimer newCon
436 utc <- getCurrentTime
437 let utc' = formatTime defaultTimeLocale "%s" utc
438 warn $ "IDLE" <> bshow utc' <> " " <> bshow (pingIdle me, pingTimeOut me)
439 -}
414 atomically $ announce (conkey,RequiresPing) 440 atomically $ announce (conkey,RequiresPing)
415 handleEOF conkey mvar newCon 441 handleEOF conkey mvar newCon
416 442
@@ -701,7 +727,20 @@ pingBump me = do
701 (1000*pingIdle me,PingIdle) 727 (1000*pingIdle me,PingIdle)
702 takeTMVar (pingStarted me) 728 takeTMVar (pingStarted me)
703 when b $ throwTo (pingThread me) $ ErrorCall "" 729 when b $ throwTo (pingThread me) $ ErrorCall ""
730 {-
731 utc <- getCurrentTime
732 let utc' = formatTime defaultTimeLocale "%s" utc
733 warn $ "BUMP " <> bshow utc' <> " " <> bshow (pingIdle me, pingTimeOut me)
734 -}
704 atomically $ putTMVar (pingStarted me) b 735 atomically $ putTMVar (pingStarted me) b
736{-
737pingBump me = do
738 b <- atomically $ do
739 when (pingIdle me /= 0) $
740 putTMVar (pingDelay me) (1000*pingIdle me,PingIdle)
741 readTMVar (pingStarted me)
742 when b $ throwTo (pingThread me) $ ErrorCall ""
743-}
705 744
706pingWait :: PingMachine -> STM PingEvent 745pingWait :: PingMachine -> STM PingEvent
707pingWait me = do 746pingWait me = do
diff --git a/test-server.hs b/test-server.hs
new file mode 100644
index 00000000..795a8190
--- /dev/null
+++ b/test-server.hs
@@ -0,0 +1,541 @@
1{-# LANGUAGE OverloadedStrings #-}
2module Main where
3
4import Debug.Trace
5import Control.Exception (evaluate) -- ,handle,SomeException(..),bracketOnError)
6import Control.Exception ({-evaluate,-}handle,SomeException(..),bracketOnError,ErrorCall(..))
7import System.IO.Error (ioeGetErrorType)
8import Server
9import Control.Monad
10import Control.Monad.Trans.Resource
11import Control.Monad.IO.Class
12import Control.Monad.STM
13import Control.Monad.Fix
14import Control.Concurrent (threadDelay,forkOS,forkIO)
15import Control.Concurrent.STM.TMVar
16import Control.Concurrent.STM.TChan
17import Network.Socket
18import System.Process.Internals
19import System.Process
20import Data.Char
21import System.IO hiding (isEOF)
22import System.Posix.Signals hiding (Ignore)
23
24
25makeGots sv = do
26 let chan = serverEvent sv
27 gotchan <- atomically $ dupTChan chan
28 forkIO $ do
29 fix $ \loop -> do
30 (k,e) <- atomically $ readTChan chan
31 case e of
32 Connection pingflag read write -> todo
33 EOF -> todo
34 loop
35 return gotchan
36
37isConnection (_,Connection {}) = True
38isConnection _ = False
39isPending want (_,HalfConnection got) | got/=want = True
40isPending _ _ = False
41isRead str (_,Got r) | r==str = True
42isRead _ _ = False
43isEOF (_,EOF) = True
44isEOF _ = False
45
46-- localhost port = SockAddrInet port 127
47localhost port = SockAddrInet6 port 0 (0,0,0,1) 0
48
49withServer f = runResourceT $ do
50 sv <- server
51 result <- liftIO $ f sv
52 release (serverReleaseKey sv)
53 return result
54
55writeToPort port str = do
56 s <- readProcess "/usr/bin/socat" ["-","TCP6:localhost:"++show port] str
57 reverse s `seq` return ()
58
59connectToPort port = do
60 (inp,outp,err,p) <-
61 runInteractiveProcess "/usr/bin/socat"
62 ["-","TCP6:localhost:"++show port]
63 Nothing
64 Nothing
65 hSetBuffering inp NoBuffering
66 hSetBuffering outp NoBuffering
67 hSetBuffering err NoBuffering
68 forkOS $ do putStrLn $ "SOCAT-ConnectToPort:"++show (port,(inp,outp,err))
69 hGetContents err >>= putStrLn
70 return (inp,outp,err,p)
71
72listenOnPort port = do
73 putStrLn $ "socat - TCP6-LISTEN:"++show port++",fork"
74 (inp,outp,err,p) <-
75 runInteractiveProcess "/usr/bin/socat"
76 ["-","TCP6-LISTEN:"++show port++",fork"]
77 Nothing
78 Nothing
79 hSetBuffering inp NoBuffering
80 hSetBuffering outp NoBuffering
81 hSetBuffering err NoBuffering
82 forkOS $ do { putStrLn "SOCAT-listenOnPort:"; hGetContents err >>= putStrLn }
83 -- forkOS $ do { putStrLn "SOCAT-listenOnPort:"; hGetContents outp >>= putStrLn }
84 return (inp,outp,err,p)
85
86stopListening (inp,outp,err,p) = do
87 {-
88 forkOS $ do
89 o <- hGetContents outp
90 void $ evaluate (length o)
91 forkOS $ do
92 e <- hGetContents err
93 void $ evaluate (length e)
94 threadDelay 1000000
95 hClose inp
96 threadDelay 1000000
97 forkOS $ do
98 threadDelay 100000
99 mapM_ hClose [outp,err]
100 -}
101 withProcessHandle p $ \p -> do
102 case p of
103 OpenHandle pid -> trace ("interrupting: "++show pid)
104 $ signalProcess sigINT pid
105 _ -> return ()
106 return (p,())
107 {-
108 threadDelay 500000
109 terminateProcess p
110 -}
111 e <- waitForProcess p
112 putStrLn $ "SOCAT-LISTEN exit: "++show e
113
114
115
116chanContents ch = do
117 x <- atomically $ do
118 bempty <- isEmptyTChan ch
119 if bempty
120 then return Nothing
121 else fmap Just $ readTChan ch
122 maybe (return [])
123 (\x -> do
124 xs <- chanContents ch
125 return (x:xs))
126 x
127
128control sv = atomically . putTMVar (serverCommand sv)
129
130testListen = do
131 let send con str = do hPutStr con str
132 hFlush con
133 threadDelay 100000
134 events <- withServer $ \sv -> do
135 let _ = sv :: Server SockAddr
136 events = serverEvent sv
137 params :: ConnectionParameters SockAddr
138 params = connectionDefaults (return . snd)
139 control sv (Listen 39242 params)
140 h1@(con1,con2,_,_)<- connectToPort 39242
141 send con1 "Joe was here"
142 control sv (Ignore 39242)
143 threadDelay 500000
144 stopListening h1
145 threadDelay 500000
146 return events
147 e <- chanContents events
148 putStrLn $ "testListen: "++ show e
149 return $
150 and [ length e == 3
151 , isConnection $ e !! 0
152 , isRead "Joe was here" $ e !! 1
153 , isEOF $ e !! 2
154 ]
155
156
157testReplace = do
158 let send con str = do hPutStrLn con str
159 hFlush con
160 threadDelay 100000
161 events <- withServer $ \sv -> do
162 let _ = sv :: Server ()
163 events = serverEvent sv
164 params = connectionDefaults (const $ return ())
165 control sv (Listen 39242 params)
166 h1@(con1,_,_,_)<- connectToPort 39242
167 send con1 "Joe was here"
168 h2@(con2,_,_,_) <- connectToPort 39242
169 send con2 "Jim also"
170 send con1 "What?"
171 threadDelay 500000
172 stopListening h1 -- misnomer
173 stopListening h2 -- misnomer
174 threadDelay 500000
175 return events
176 e <- chanContents events
177 -- [([::ffff:127.0.0.1]:43722,Connection)
178 -- ,([::ffff:127.0.0.1]:43722,Got "Joe was here\n")
179 -- ,([::ffff:127.0.0.1]:43723,Connection)
180 -- ,([::ffff:127.0.0.1]:43723,Got "Jim also\n")
181 -- ,([::ffff:127.0.0.1]:43722,Got "What?\n")
182 -- ,([::ffff:127.0.0.1,EOF)]:43722
183 -- ,([::ffff:127.0.0.1,EOF)]:43723]
184 -- putStrLn $ show e
185 putStrLn $ "testReplace: "++ show e
186 return $ case e of
187 [(_,Connection {})
188 ,(_,Got "Joe was here\n")
189 ,(_,EOF)
190 ,(_,Connection {})
191 ,(_,Got "Jim also\n")
192 ,(_,EOF)]
193 -> True
194 _ -> False
195
196testPendingOut = do
197 let send con str = do hPutStr con str
198 hFlush con
199 threadDelay 100000
200 events <- withServer $ \sv -> do
201 let _ = sv :: Server SockAddr
202 events = serverEvent sv
203 params :: ConnectionParameters SockAddr
204 params = (connectionDefaults (return . snd))
205 { duplex = False }
206 control sv (Listen 39249 params)
207 h1@(con1,con2,_,_)<- connectToPort 39249
208 send con1 "Joe was here"
209 stopListening h1
210 threadDelay 500000
211 return events
212
213 e <- chanContents events
214 putStrLn $ "testPendingOut: "++ show e
215 return $
216 and [ length e == 3
217 , isPending Out $ e !! 0
218 , isRead "Joe was here" $ e !! 1
219 , isEOF $ e !! 2
220 ]
221
222testReplacePendingOut = do
223 let send con str = do hPutStrLn con str
224 hFlush con
225 threadDelay 100000
226 events <- withServer $ \sv -> do
227 let _ = sv :: Server ()
228 events = serverEvent sv
229 params = (connectionDefaults (const $ return ()))
230 { duplex = False }
231 control sv (Ignore 39242)
232 control sv (Listen 39242 params)
233 threadDelay 500000
234 h1@(con1,_,_,_) <- connectToPort 39242
235 send con1 "Joe was here"
236 h2@(con2,_,_,_) <- connectToPort 39242
237 send con2 "Jim also"
238 send con1 "What?"
239 threadDelay 500000
240 control sv (Ignore 39242)
241 threadDelay 500000
242 stopListening h1 -- misnomer
243 stopListening h2 -- misnomer
244 threadDelay 500000
245 return events
246 e <- chanContents events
247 putStrLn $ "testReplacePendingOut: "++ show e
248 return $ case e of
249 [ (_,HalfConnection In)
250 ,(_,Got "Joe was here\n")
251 ,(_,EOF)
252 ,(_,HalfConnection In)
253 ,(_,Got "Jim also\n")
254 ,(_,EOF)]
255 -> True
256 _ -> False
257
258testReplacePendingIn = do
259 let send con str = do hPutStrLn con str
260 hFlush con
261 threadDelay 100000
262 (events,socat) <- withServer $ \sv -> do
263 let _ = sv :: Server ()
264 events = serverEvent sv
265 params = (connectionDefaults (const $ return ()))
266 { duplex = False }
267 threadDelay 500000
268 socat <- listenOnPort 39242
269 threadDelay 500000
270 control sv (Connect (localhost 39242) params)
271 control sv (Connect (localhost 39242) params)
272 return (events,socat)
273 threadDelay 500000
274 stopListening socat
275 threadDelay 500000
276 e <- chanContents events
277 putStrLn $ "testReplacePendingIn: "++ show e
278 return $ e==[((),HalfConnection Out)
279 ,((),EOF)
280 ,((),HalfConnection Out)
281 ,((),EOF)]
282
283testPromotePendingOut = do
284 putStrLn "----------- testPromotePendingOut"
285 hFlush stdout
286 let send con str = do hPutStr con str
287 hFlush con
288 threadDelay 100000
289 (events,s,socat) <- withServer $ \sv -> do
290 let _ = sv :: Server ()
291 events = serverEvent sv
292 params = (connectionDefaults (const $ return ()))
293 { duplex = False }
294 control sv (Ignore 39244)
295 threadDelay 500000
296 control sv (Listen 39244 params)
297 socat <- listenOnPort 39243
298 h@(con1,con2,_,_) <- connectToPort 39244
299 putStrLn $ "connected to 39244, Sending Joe was here"
300 send con1 "Joe was here"
301 threadDelay 500000
302 putStrLn $ "Connecting to 39243"
303 control sv (Connect (localhost 39243) params)
304 threadDelay 500000
305 putStrLn $ "probably connected to 39243"
306 control sv (Send () "and jim")
307 putStrLn $ "connected to 39244, Sending Joe was here twice"
308 hFlush stdout
309 send con1 "Joe was here twice"
310 threadDelay 500000
311 s <- fmap (take 7) $ hGetContents ((\(_,x,_,_)->x) socat)
312 last s `seq` threadDelay 500000
313 stopListening h -- misnomer
314 threadDelay 50000
315 return (events,s,socat)
316 stopListening socat
317 threadDelay 500000
318 e <- chanContents events
319 putStrLn $ "testPromotePendingOut: "++ show (s,e)
320 -- testPromotePendingOut: ("and jim",[HalfConnection () In,((),Got "Joe was here"),((),Read () "Joe was here twice",((),EOF)]),Connection)
321 --
322 return . and $
323 [ s== "and jim"
324 , e== [ ((),HalfConnection In)
325 , ((),Got "Joe was here")
326 , ((),Connection {})
327 , ((),Got "Joe was here twice")
328 , ((),EOF) ]
329 ]
330
331testPromotePendingIn = do
332 putStrLn "----------- testPromotePendingIn"
333 hFlush stdout
334 let send con str = do handle (\e -> putStrLn . show $ ioeGetErrorType e) $ do
335 hPutStrLn con str
336 hFlush con
337 threadDelay 500000
338 (events,socat,s) <- withServer $ \sv -> do
339 let _ = sv :: Server ()
340 events = serverEvent sv
341 params = (connectionDefaults (const $ return ()))
342 { duplex = False }
343
344 -- Outgoing connection
345 socat <- listenOnPort 39248
346 threadDelay 500000
347 putStrLn $ "Connecting to 39248..."
348 control sv (Connect (localhost 39248) params)
349 threadDelay 1000000
350 putStrLn $ "...probably connected to 39248"
351 control sv (Send () "and jim")
352 threadDelay 1000000
353
354 s <- fmap (take 7) $ hGetContents ((\(_,x,_,_)->x) socat)
355 length s `seq` threadDelay 500000
356
357 control sv (Listen 39247 params)
358 threadDelay 500000
359 h@(con1,con2,_,_) <- connectToPort 39247
360 send con1 "howdy!"
361 h2@(con1',con2',_,_) <- connectToPort 39247
362 threadDelay 500000
363 send con1' "what?"
364 threadDelay 1000000
365 hClose con1
366 hClose con1'
367 threadDelay 1000000
368 stopListening socat
369 threadDelay 1000000
370
371 return (events,socat,s)
372 e <- chanContents events
373 putStrLn $ "testPromotePendingIn: "++ show (s,e)
374 -- testPromotePendingIn: ("and jim",[HalfConnection () Out,((),((),Got "howdy!\n"),((),EOF (),HalfConnection () In,Read () "what?\n",EOF (),EOF)]),Connection)
375 -- ("and jim",[HalfConnection () Out,((),((),Got "howdy!\n"),((),HalfConnection () In,Read () "what?\n",EOF (),EOF)]),Connection)
376 return . and $
377 [ s == "and jim"
378 , e == [ ((),HalfConnection Out)
379 ,((),Connection {})
380 ,((),Got "howdy!\n")
381 ,((),EOF)
382 ,((),HalfConnection In)
383 ,((),Got "what?\n")
384 ,((),EOF)]
385 ]
386
387testPing = do
388 putStrLn "----------- testPing"
389 let send con str = do handle (\e -> putStrLn . show $ ioeGetErrorType e) $ do
390 hPutStrLn con str
391 hFlush con
392 threadDelay 500000
393 events <- withServer $ \sv -> do
394 let _ = sv :: Server ()
395 events = serverEvent sv
396 params = (connectionDefaults (const $ return ()))
397 { pingInterval = 2000
398 , timeout = 1000 }
399 control sv (Listen 32957 params)
400 threadDelay 500000
401 socat@(h,_,_,_) <- connectToPort 32957
402
403 -- putStrLn $ "sending hey you!"
404 send h "hey you!"
405 -- putStrLn $ "delay"
406 threadDelay 3500000 -- ping timeout
407 -- putStrLn $ "sending what?"
408 send h "what?" -- lost due to timeout
409 -- putStrLn $ "delay-2"
410 threadDelay 500000
411 -- putStrLn $ "close h"
412 hClose h
413
414 threadDelay 500000
415 socat@(h,_,_,_) <- connectToPort 32957
416 send h "try 2: hey you!"
417 threadDelay 2500000 -- ping warning
418 send h "try 2: what?"
419 threadDelay 1000000 -- no warning or timeout
420 send h "try 2: yes."
421 stopListening socat
422 threadDelay 1000000
423 return events
424
425 e <- chanContents events
426 putStrLn $ "testPing: "++show e
427 -- testPing: [((),Connection <STM action> <IO action> <function>)
428{-
429,((),Got "hey you!\n")
430,((),RequiresPing)
431,((),RequiresPing)
432,((),Got "what?\n")
433,((),EOF)
434,((),Connection <STM action> <IO action> <function>)
435,((),Got "try 2: hey you!\n")
436,((),RequiresPing)
437,((),Got "try 2: what?\n")
438,((),Got "try 2: yes.\n")
439,((),EOF)]
440testPing: [((),Connection <STM action> <IO action> <function>)
441,((),Got "hey you!\n")
442,((),RequiresPing)
443,((),Got "what?\n")
444,((),RequiresPing)
445,((),EOF)
446,((),Connection <STM action> <IO action> <function>)
447,((),Got "try 2: hey you!\n")
448,((),RequiresPing)
449,((),Got "try 2: what?\n")
450,((),RequiresPing)]
451testPing: [((),Connection <STM action> <IO action> <function>)
452,((),Got "hey you!\n")
453,((),RequiresPing)
454,((),Got "what?\n")
455,((),RequiresPing)
456,((),EOF)
457,((),Connection <STM action> <IO action> <function>)
458,((),Got "try 2: hey you!\n")
459,((),RequiresPing)
460,((),Got "try 2: what?\n")
461,((),Got "try 2: yes.\n")
462,((),EOF)]
463
464-}
465
466 return $ e == [((),Connection {})
467 ,((),Got "hey you!\n")
468 ,((),RequiresPing)
469 ,((),EOF)
470 ,((),Connection {})
471 ,((),Got "try 2: hey you!\n")
472 ,((),RequiresPing)
473 ,((),Got "try 2: what?\n")
474 ,((),Got "try 2: yes.\n")
475 ,((),EOF)]
476
477testDisabledPing = do
478 let send con str = do hPutStrLn con str
479 hFlush con
480 threadDelay 500000
481 events <- withServer $ \sv -> do
482 let _ = sv :: Server ()
483 events = serverEvent sv
484 params = (connectionDefaults (const $ return ()))
485 { pingInterval = 0
486 , timeout = 0 }
487 control sv (Listen 32958 params)
488 threadDelay 500000
489 socat@(h,_,_,_) <- connectToPort 32958
490
491 send h "hey you!"
492 threadDelay 3500000 -- ping timeout
493 send h "what?" -- lost due to timeout
494 threadDelay 500000
495 hClose h
496
497 threadDelay 500000
498 socat@(h,_,_,_) <- connectToPort 32958
499 send h "try 2: hey you!"
500 threadDelay 2500000 -- ping warning
501 send h "try 2: what?"
502 threadDelay 1000000 -- no warning or timeout
503 send h "try 2: yes."
504 stopListening socat
505 threadDelay 5000000
506 return events
507
508 e <- chanContents events
509 putStrLn $ "testDisabledPing: "++show e
510 return $ e == [((),Connection {})
511 ,((),Got "hey you!\n")
512 ,((),Got "what?\n")
513 ,((),EOF)
514 ,((),Connection {})
515 ,((),Got "try 2: hey you!\n")
516 ,((),Got "try 2: what?\n")
517 ,((),Got "try 2: yes.\n")
518 ,((),EOF)]
519main = do
520 result1 <- testListen
521 result2 <- testReplace
522 result3 <- testPendingOut
523 result4 <- testReplacePendingOut
524 threadDelay 100000
525 result5 <- testReplacePendingIn
526 result6 <- testPromotePendingOut
527 result7 <- testPromotePendingIn
528 result8 <- testPing
529 result9 <- testDisabledPing
530 let passOrFail str True = putStrLn $ str ++ ": passed"
531 passOrFail str False = putStrLn $ str ++ ": failed"
532 passOrFail "testListen" result1
533 passOrFail "testReplace" result2
534 passOrFail "testPendingOut" result3
535 passOrFail "testReplacePendingOut" result4
536 passOrFail "testReplacePendingIn" result5
537 passOrFail "testPromotePendingOut" result6
538 passOrFail "testPromotePendingIn" result7
539 passOrFail "testPing" result8
540 passOrFail "testDisabledPing" result9
541 return ()