diff options
author | joe <joe@jerkface.net> | 2013-06-15 15:07:19 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2013-06-15 15:07:19 -0400 |
commit | 9fd2107e6a7469fe7ba51448e4fe195bf54d7d29 (patch) | |
tree | bb37572b478170e461990695e7d9e6ab823f7606 /Presence/Server.hs |
started project
Diffstat (limited to 'Presence/Server.hs')
-rw-r--r-- | Presence/Server.hs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/Presence/Server.hs b/Presence/Server.hs new file mode 100644 index 00000000..c41f047f --- /dev/null +++ b/Presence/Server.hs | |||
@@ -0,0 +1,81 @@ | |||
1 | {-# LANGUAGE TypeFamilies #-} | ||
2 | {-# LANGUAGE TypeOperators #-} | ||
3 | module Server where | ||
4 | |||
5 | import Network.Socket | ||
6 | import qualified Data.ByteString as S (ByteString) | ||
7 | import Data.ByteString.Lazy.Char8 as L | ||
8 | ( ByteString | ||
9 | , hPutStrLn | ||
10 | , fromChunks | ||
11 | , putStrLn ) | ||
12 | import Data.ByteString.Char8 | ||
13 | ( hGetNonBlocking | ||
14 | ) | ||
15 | import System.IO | ||
16 | ( Handle | ||
17 | , IOMode(..) | ||
18 | , hSetBuffering | ||
19 | , BufferMode(..) | ||
20 | , hWaitForInput | ||
21 | , hClose | ||
22 | , hIsEOF | ||
23 | ) | ||
24 | import Control.Monad | ||
25 | import Control.Monad.Fix (fix) | ||
26 | import Todo | ||
27 | import Control.Concurrent (forkIO) | ||
28 | import Control.Exception (handle,SomeException(..)) | ||
29 | import Data.HList | ||
30 | import Data.HList.TypeEqGeneric1() | ||
31 | import Data.HList.TypeCastGeneric1() | ||
32 | |||
33 | |||
34 | newtype ConnId = ConnId Int | ||
35 | deriving Eq | ||
36 | |||
37 | newtype ConnectionFinalizer = ConnectionFinalizer (IO ()) | ||
38 | |||
39 | getPacket h = do { hWaitForInput h (-1) ; fmap (fromChunks . (:[])) $ hGetNonBlocking h 1024 } | ||
40 | |||
41 | {- | ||
42 | doServer :: | ||
43 | HList st | ||
44 | => PortNumber :*: st | ||
45 | -> ( Handle :*: ConnId :*: PortNumber :*: st | ||
46 | -> S.ByteString | ||
47 | -> (() -> IO ()) | ||
48 | -> IO () ) | ||
49 | -> IO b | ||
50 | -} | ||
51 | doServer port g startCon = runServer2 port (runConn2 g) | ||
52 | where | ||
53 | runConn2 g st (sock,_) = do | ||
54 | h <- socketToHandle sock ReadWriteMode | ||
55 | hSetBuffering h NoBuffering | ||
56 | st'' <- startCon (h .*. st) | ||
57 | handle (\(SomeException _) -> return ()) $ fix $ \loop -> do | ||
58 | let continue () = hIsEOF h >>= flip when loop . not | ||
59 | packet <- getPacket h | ||
60 | g st'' packet continue | ||
61 | let ConnectionFinalizer cleanup = hOccursFst st'' | ||
62 | cleanup | ||
63 | hClose h | ||
64 | |||
65 | {- | ||
66 | runServer2 :: | ||
67 | Num num => | ||
68 | PortNumber -> (num -> (Socket, SockAddr) -> IO b -> IO b) -> IO b | ||
69 | -} | ||
70 | runServer2 st@(HCons port _) go = do | ||
71 | sock <- socket AF_INET Stream 0 | ||
72 | setSocketOption sock ReuseAddr 1 | ||
73 | bindSocket sock (SockAddrInet port iNADDR_ANY) | ||
74 | listen sock 2 | ||
75 | mainLoop sock (ConnId 0) go | ||
76 | where | ||
77 | mainLoop sock idnum@(ConnId n) go = do | ||
78 | con <- accept sock | ||
79 | forkIO $ go (idnum .*. st) con | ||
80 | mainLoop sock (ConnId (n+1)) go | ||
81 | |||