-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathRawServer.hs
79 lines (71 loc) · 2.41 KB
/
RawServer.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
module Main where
import Message
import Utils
import Server
import Network.Socket
import System.Environment
import Control.Exception
import Data.Aeson
import Data.ByteString.Lazy.UTF8 (fromString, toString)
import Data.List.Split
import Control.Concurrent
import Control.Monad
import Data.Maybe
import System.Random
import Data.Time
import Data.List
import qualified Data.HashMap.Strict as HM
import qualified Data.HashSet as HS
tryGet :: Chan a -> IO (Maybe a)
tryGet chan = do
empty <- isEmptyChan chan
if empty then
return Nothing
else do
response <- readChan chan
return $ Just response
-- This function runs in its own thread, receiving messages and adding them to a "channel"
receiver :: Socket -> Chan Message -> IO ()
receiver s messages = do
forever $ do
msg <- recv s 8192
let splitR = splitOn "\n" msg
let fsMessages = map fromString splitR
let mMessages = map decode fsMessages :: [Maybe Message]
writeList2Chan messages $ catMaybes mMessages
getSocket :: String -> IO Socket
getSocket id = do
soc <- socket AF_UNIX Stream defaultProtocol
connect soc $ SockAddrUnix id
return soc
-- This is the main server loop. It attempts to read a message from the
-- channel, then steps it
serverLoop :: Server -> Chan Message -> Socket -> IO ()
serverLoop server chan socket = do
message <- tryGet chan
time <- getCurrentTime
possibleTimeout <- getStdRandom $ randomR timeoutRange
newMid <- getStdRandom $ randomR (100000, 999999)
-- This is where the server receives the message and then responds appropriately
let server' = step (show (newMid :: Int)) time $ receiveMessage server time possibleTimeout message
mapped = map (((flip (++)) "\n") . toString . encode) $ sendMe server'
mapM (send socket) mapped
serverLoop (server' { sendMe = [] } ) chan socket -- recursive
start :: Server -> Chan Message -> Socket -> IO ()
start server chan socket = do
tid <- forkIO $ receiver socket chan
serverLoop server chan socket
killThread tid
initialServer :: String -> [String] -> IO Server
initialServer myID otherIDs = do
timeout <- getStdRandom $ randomR timeoutRange
time <- getCurrentTime
return $ initServer myID otherIDs time timeout
main :: IO ()
main = do
args <- getArgs
messageChan <- newChan
let myID = head args
otherIDs = tail args
server <- initialServer myID otherIDs
withSocketsDo $ bracket (getSocket myID) sClose (start server messageChan)