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
80
81
82
83
84
85
86
87
88
89
------------------------------------------------------------------------------
--- Library to support network programming with sockets.
--- In standard applications, the server side uses the operations
--- `listenOn` and `socketAccept` to provide some service
--- on a socket, and the client side uses the operation
--- `connectToSocket` to request a service.
---
--- @author Michael Hanus
--- @version December 2018
------------------------------------------------------------------------------

module Network.Socket
  (Socket, listenOn, listenOnFresh,
   accept, waitForSocketAccept, close, connectToSocket)
 where

import System.IO (Handle)

--- The abstract type of sockets.
external data Socket

---------------------------------------------------------------------
-- Server side operations:

--- Creates a server side socket bound to a given port number.
listenOn :: Int -> IO Socket
listenOn port = prim_listenOn $# port

prim_listenOn :: Int -> IO Socket
prim_listenOn external

--- Creates a server side socket bound to a free port.
--- The port number and the socket is returned.
listenOnFresh :: IO (Int,Socket)
listenOnFresh external


--- Returns a connection of a client to a socket.
--- The connection is returned as a pair consisting of a string identifying
--- the client (the format of this string is implementation-dependent)
--- and a handle to a stream communication with the client.
--- The handle is both readable and writable.
--- Only IPv4 connections are currently possible.
accept :: Socket -> IO (String,Handle)
accept s = prim_socketAccept $## s

prim_socketAccept :: Socket -> IO (String,Handle)
prim_socketAccept external


--- Waits until a connection of a client to a socket is available.
--- If no connection is available within the time limit, it returns Nothing,
--- otherwise the connection is returned as a pair consisting
--- of a string identifying the client
--- (the format of this string is implementation-dependent)
--- and a handle to a stream communication with the client.
--- @param socket - a socket
--- @param timeout - milliseconds to wait for input (< 0 : no time out)
waitForSocketAccept :: Socket -> Int -> IO (Maybe (String,Handle))
waitForSocketAccept s timeout = (prim_waitForSocketAccept $## s) $# timeout

prim_waitForSocketAccept :: Socket -> Int -> IO (Maybe (String,Handle))
prim_waitForSocketAccept external


--- Closes a server socket.
close :: Socket -> IO ()
close s = prim_sClose $## s

prim_sClose :: Socket -> IO ()
prim_sClose external


---------------------------------------------------------------------
-- Client side operations:

--- Creates a new connection to a Unix socket.
--- Only IPv4 connections are currently possible.
--- @param host - the host name of the connection
--- @param port - the port number of the connection
--- @return the handle of the stream (connected to the port port@host)
---         which is both readable and writable
connectToSocket :: String -> Int -> IO Handle
connectToSocket host port = (prim_connectToSocket $## host) $# port

prim_connectToSocket :: String -> Int -> IO Handle
prim_connectToSocket external

---------------------------------------------------------------------