author | unc0rr |
Sat, 16 Feb 2013 23:28:16 +0400 | |
changeset 8507 | f4475782cf45 |
parent 8506 | 3889dab021b8 |
child 8515 | 222f43420615 |
permissions | -rw-r--r-- |
8474
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
1 |
{-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings #-} |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
2 |
module Main where |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
3 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
4 |
import qualified Control.Exception as Exception |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
5 |
import System.IO |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
6 |
import System.Log.Logger |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
7 |
import qualified Data.ConfigFile as CF |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
8 |
import Control.Monad.Error |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
9 |
import System.Directory |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
10 |
import Control.Monad.State |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
11 |
import Control.Concurrent.Chan |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
12 |
import Control.Concurrent |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
13 |
import Network |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
14 |
import Network.BSD |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
15 |
import Network.Socket hiding (recv) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
16 |
import Network.Socket.ByteString |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
17 |
import qualified Data.ByteString.Char8 as B |
8497
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
18 |
import qualified Data.ByteString as BW |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
19 |
import qualified Codec.Binary.Base64 as Base64 |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
20 |
import System.Process |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
21 |
import Data.Maybe |
8474
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
22 |
#if !defined(mingw32_HOST_OS) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
23 |
import System.Posix |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
24 |
#endif |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
25 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
26 |
data Message = Packet [B.ByteString] |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
27 |
deriving Show |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
28 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
29 |
protocolNumber = "43" |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
30 |
|
8497
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
31 |
checkReplay :: [B.ByteString] -> IO () |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
32 |
checkReplay msgs = do |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
33 |
tempDir <- getTemporaryDirectory |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
34 |
(fileName, h) <- openBinaryTempFile tempDir "checker-demo" |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
35 |
B.hPut h . BW.pack . concat . map (fromJust . Base64.decode . B.unpack) $ msgs |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
36 |
hFlush h |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
37 |
hClose h |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
38 |
|
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
39 |
(_, _, Just hErr, _) <- createProcess (proc "/usr/home/unC0Rr/Sources/Hedgewars/Releases/0.9.18/bin/hwengine" |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
40 |
["/usr/home/unC0Rr/.hedgewars" |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
41 |
, "/usr/home/unC0Rr/Sources/Hedgewars/Releases/0.9.18/share/hedgewars/Data" |
8506 | 42 |
, fileName |
43 |
, "--set-audio" |
|
44 |
, "0" |
|
45 |
, "0" |
|
46 |
, "0" |
|
47 |
]) |
|
8497
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
48 |
{std_err = CreatePipe} |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
49 |
hSetBuffering hErr LineBuffering |
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
50 |
|
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
51 |
|
8474
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
52 |
takePacks :: State B.ByteString [[B.ByteString]] |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
53 |
takePacks = do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
54 |
modify (until (not . B.isPrefixOf pDelim) (B.drop 2)) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
55 |
packet <- state $ B.breakSubstring pDelim |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
56 |
buf <- get |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
57 |
if B.null buf then put packet >> return [] else |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
58 |
if B.null packet then return [] else do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
59 |
packets <- takePacks |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
60 |
return (B.splitWith (== '\n') packet : packets) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
61 |
where |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
62 |
pDelim = "\n\n" |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
63 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
64 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
65 |
recvLoop :: Socket -> Chan Message -> IO () |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
66 |
recvLoop s chan = |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
67 |
((receiveWithBufferLoop B.empty >> return "Connection closed") |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
68 |
`Exception.catch` (\(e :: Exception.SomeException) -> return . B.pack . show $ e) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
69 |
) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
70 |
>>= disconnected |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
71 |
where |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
72 |
disconnected msg = writeChan chan $ Packet ["BYE", msg] |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
73 |
receiveWithBufferLoop recvBuf = do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
74 |
recvBS <- recv s 4096 |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
75 |
unless (B.null recvBS) $ do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
76 |
let (packets, newrecvBuf) = runState takePacks $ B.append recvBuf recvBS |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
77 |
forM_ packets sendPacket |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
78 |
receiveWithBufferLoop $ B.copy newrecvBuf |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
79 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
80 |
sendPacket packet = writeChan chan $ Packet packet |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
81 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
82 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
83 |
session :: B.ByteString -> B.ByteString -> Socket -> IO () |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
84 |
session l p s = do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
85 |
noticeM "Core" "Connected" |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
86 |
coreChan <- newChan |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
87 |
forkIO $ recvLoop s coreChan |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
88 |
forever $ do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
89 |
p <- readChan coreChan |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
90 |
case p of |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
91 |
Packet p -> do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
92 |
debugM "Network" $ "Recv: " ++ show p |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
93 |
onPacket p |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
94 |
where |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
95 |
answer :: [B.ByteString] -> IO () |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
96 |
answer p = do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
97 |
debugM "Network" $ "Send: " ++ show p |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
98 |
sendAll s $ B.unlines p `B.snoc` '\n' |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
99 |
onPacket :: [B.ByteString] -> IO () |
8479
8d71109b04d2
Some work on loading replay and interaction with checker
unc0rr
parents:
8474
diff
changeset
|
100 |
onPacket ("CONNECTED":_) = do |
8d71109b04d2
Some work on loading replay and interaction with checker
unc0rr
parents:
8474
diff
changeset
|
101 |
answer ["CHECKER", protocolNumber, l, p] |
8d71109b04d2
Some work on loading replay and interaction with checker
unc0rr
parents:
8474
diff
changeset
|
102 |
answer ["READY"] |
8474
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
103 |
onPacket ["PING"] = answer ["PONG"] |
8497
c5605c6f5bb3
Hack checker to run engine with record file received (uses hardcoded paths)
unc0rr
parents:
8479
diff
changeset
|
104 |
onPacket ("REPLAY":msgs) = checkReplay msgs |
8474
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
105 |
onPacket ("BYE" : xs) = error $ show xs |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
106 |
onPacket _ = return () |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
107 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
108 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
109 |
main :: IO () |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
110 |
main = withSocketsDo $ do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
111 |
#if !defined(mingw32_HOST_OS) |
8507 | 112 |
installHandler sigPIPE Ignore Nothing |
113 |
installHandler sigCHLD Ignore Nothing |
|
8474
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
114 |
#endif |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
115 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
116 |
updateGlobalLogger "Core" (setLevel DEBUG) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
117 |
updateGlobalLogger "Network" (setLevel DEBUG) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
118 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
119 |
Right (login, password) <- runErrorT $ do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
120 |
d <- liftIO $ getHomeDirectory |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
121 |
conf <- join . liftIO . CF.readfile CF.emptyCP $ d ++ "/.hedgewars/hedgewars.ini" |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
122 |
l <- CF.get conf "net" "nick" |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
123 |
p <- CF.get conf "net" "passwordhash" |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
124 |
return (B.pack l, B.pack p) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
125 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
126 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
127 |
Exception.bracket |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
128 |
setupConnection |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
129 |
(\s -> noticeM "Core" "Shutting down" >> sClose s) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
130 |
(session login password) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
131 |
where |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
132 |
setupConnection = do |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
133 |
noticeM "Core" "Connecting to the server..." |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
134 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
135 |
proto <- getProtocolNumber "tcp" |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
136 |
let hints = defaultHints { addrFlags = [AI_ADDRCONFIG, AI_CANONNAME] } |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
137 |
(addr:_) <- getAddrInfo (Just hints) (Just serverAddress) Nothing |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
138 |
let (SockAddrInet _ host) = addrAddress addr |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
139 |
sock <- socket AF_INET Stream proto |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
140 |
connect sock (SockAddrInet 46631 host) |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
141 |
return sock |
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
142 |
|
f6abe50095d2
Start work on the checker. Not it could connect to the server and... crash it.
unc0rr
parents:
diff
changeset
|
143 |
serverAddress = "netserver.hedgewars.org" |