2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
4 % Last Modified: Fri Jul 21 15:14:43 1995
5 % Darren J Moffat <moffatd@dcs.gla.ac.uk>
6 \section[SocketPrim]{Low-level socket bindings}
8 The @SocketPrim@ module is for when you want full control over the
9 sockets, something like what you have in C (which is very messy).
20 socket, -- :: Family -> SocketType -> Int -> IO Socket
21 connect, -- :: Socket -> SockAddr -> IO ()
22 bindSocket, -- :: Socket -> SockAddr -> IO ()
23 listen, -- :: Socket -> Int -> IO ()
24 accept, -- :: Socket -> IO (Socket, SockAddr)
25 getPeerName, -- :: Socket -> IO SockAddr
26 getSocketName, -- :: Socket -> IO SockAddr
28 socketPort, -- :: Socket -> IO Int
30 writeSocket, -- :: Socket -> String -> IO Int
31 readSocket, -- :: Socket -> Int -> IO (String, Int)
32 readSocketAll, -- :: Socket -> IO String
34 socketToHandle, -- :: Socket -> IO Handle
36 -- Alternative read/write interface not yet implemented.
37 -- sendto -- :: Socket -> String -> SockAddr -> IO Int
38 -- recvfrm -- :: Socket -> Int -> SockAddr -> IO (String, Int)
39 -- sendmsg -- :: Socket -> Message -> MsgFlags -> IO Int
40 -- recvmsg -- :: Socket -> MsgFlags -> IO Message
42 shutdown, -- :: Socket -> Int -> IO ()
43 sClose, -- :: Socket -> IO ()
45 inet_addr, -- :: String -> HostAddress
46 inet_ntoa, -- :: HostAddress -> String
48 sIsConnected, -- :: Socket -> IO Bool
49 sIsBound, -- :: Socket -> IO Bool
50 sIsListening, -- :: Socket -> IO Bool
51 sIsReadable, -- :: Socket -> IO Bool
52 sIsWritable, -- :: Socket -> IO Bool
64 -- The following are exported ONLY for use in the BSD module and
65 -- should not be used else where.
67 packFamily, unpackFamily,
69 packSockAddr, unpackSockAddr
77 import PreludePrimIO ( newEmptyMVar, putMVar, _MVar )
82 %************************************************************************
84 \subsection[Socket-SocketTypes]{Socket Types}
86 %************************************************************************
89 There are a few possible ways to do this. The first is convert the
90 structs used in the C library into an equivalent Haskell type. An
91 other possible implementation is to keep all the internals in the C
92 code and use an Int\# and a status flag. The second method is used here
93 since a lot of the C structures are not required to be manipulated.
94 Originally the status was non mutable so we had to return a new socket
95 each time we changed the status. This version now uses mutable
96 variables to avoid the need to do this. The result is a cleaner
97 interface and better security since the application programmer now
98 can't circumvent the status information to perform invalid operations
104 -- Returned Status Function called
105 = NotConnected -- socket
106 | Bound -- bindSocket
107 | Listening -- listen
108 | Connected -- connect/accept
109 | Error String -- Any
114 Int -- File Descriptor Part
117 Int -- Protocol Number
118 (MutableVar _RealWorld SocketStatus) -- Status Flag
121 In C bind takes either a $struct sockaddr\_in$ or a $struct
122 sockaddr\_un$ but these are always type cast to $struct sockaddr$. We
123 attempt to emulate this and provide better type checking. Note that
124 the socket family fields are redundant since this is caputured in the
125 constructor names, it has thus be left out of the Haskell $SockAddr$
130 type HostAddress = _Word
132 data SockAddr -- C Names
133 = SockAddrUnix -- struct sockaddr_un
136 | SockAddrInet -- struct sockaddr_in
138 HostAddress -- sin_addr
145 %************************************************************************
147 \subsection[Socket-Connections]{Connection Functions}
149 %************************************************************************
152 In the following connection and binding primitives. The names of the
153 equivalent C functions have been preserved where possible. It should
154 be noted that some of these names used in the C library, bind in
155 particular, have a different meaning to many Haskell programmers and
156 have thus been renamed by appending the prefix Socket.
158 Create an unconnected socket of the given family, type and protocol.
159 The most common invocation of $socket$ is the following:
162 socket AF_INET Stream 6 >>= \ my_socket ->
167 socket :: Family -> -- Family Name (usually AF_INET)
168 SocketType -> -- Socket Type (usually Stream)
169 Int -> -- Protocol Number (getProtocolByName to find value)
170 IO Socket -- Unconnected Socket
172 socket family stype protocol =
173 _ccall_ socket (packFamily family) (packSocketType stype) protocol
176 getCErrorCode `thenPrimIO` \ errno ->
179 fail "socket: Permission Denied"
181 fail "socket: No more descriptiors available"
183 fail "socket: System file table is full"
185 fail "socket: Insufficient Buffer space to create socket"
187 fail ("socket: Protocol " ++ show protocol ++
188 " not supported for Family " ++ show family)
190 fail ("socket: Protocol " ++ show protocol ++
191 " wrong type for socket")
193 fail ("socket: " ++ (errorCodeToStr errno))
196 newVar NotConnected `thenPrimIO` \ status ->
197 return (MkSocket s family stype protocol status)
200 Given a port number this {\em binds} the socket to that port. This
201 means that the programmer is only interested in data being sent to
202 that port number. The $Family$ passed to $bindSocket$ must
203 be the same as that passed to $socket$. If the special port
204 number $aNY\_PORT$ is passed then the system assigns the next
207 Port numbers for standard unix services can be found by calling
208 $getServiceEntry$. These are traditionally port numbers below
209 1000; although there are afew, namely NFS and IRC, which used higher
212 The port number allocated to a socket bound by using $aNY\_PORT$ can be
213 found by calling $port$
216 bindSocket :: Socket -> -- Unconnected Socket
217 SockAddr -> -- Address to Bind to
220 bindSocket (MkSocket s family stype protocol status) addr =
221 readVar status `thenST` \ currentStatus ->
222 if currentStatus /= NotConnected then
223 fail ("bindSocket: can't peform bind on socket in status " ++
226 packSockAddr addr `thenPrimIO` \ addr' ->
227 let (_,sz) = boundsOfByteArray addr' in
228 _casm_ ``%r = bind(%0, (struct sockaddr*)%1, %2);''
229 s addr' sz `thenPrimIO` \ result ->
231 getCErrorCode `thenPrimIO` \ errno ->
234 fail "bindSocket: The requested address is protected"
236 fail "bindSocket: Address in use by another process"
238 fail "bindSocket: Address not available"
240 fail "bindSocket: invalid descriptor"
242 fail "bindSocket: name parameter not in vaild user address space"
244 fail "bindSocket: namelen invalid size for given family"
246 fail "bindSocket: attempt to bind a non socket descriptor"
248 fail ("bindSocket: " ++ (errorCodeToStr errno))
251 writeVar status (Bound) `seqPrimIO`
256 Make a connection to an already opened socket on a given machine and port.
257 assumes that we have already called createSocket, othewise it will fail.
259 This is the dual to $bindSocket$. The {\em server} process will
260 usually bind to a port number, the {\em client} will then connect to
261 the same port number. Port numbers of user applications are normally
262 agreed in advance, otherwise we must rely on some hacky mechanism for telling
263 the {\em otherside} what port number we have been allocated.
266 connect :: Socket -> -- Unconnected Socket
267 SockAddr -> -- Socket address stuff
270 connect (MkSocket s family stype protocol status) addr =
271 readVar status `thenST` \ currentStatus ->
272 if currentStatus /= NotConnected then
273 fail ("connect: can't peform connect on socket in status " ++
276 packSockAddr addr `thenPrimIO` \ addr' ->
277 let (_,sz) = boundsOfByteArray addr' in
278 _casm_ ``%r = connect(%0,(struct sockaddr*)%1, %2);''
279 s addr' sz `thenPrimIO` \ result ->
281 getCErrorCode `thenPrimIO` \ errno ->
284 fail "connect: address in use"
286 fail "connect: address not available on remote machine"
288 fail "connect: invalid socket address family"
290 fail ("connect: socket in non-blocking and previous " ++
291 "attempt to connect not yet complteted")
293 fail "connect: socket in not a vaild descriptor"
295 fail "connect: connection refused by peer"
297 fail "connect: address parameter outside process address space"
299 fail ("connect: socket is non-blocking and connection can " ++
300 "not be completed imediately")
302 fail "connect: connection interrupted before delivery signal"
304 fail ("connect: namlen not size of valid address for " ++
307 fail "connect: socket is already connected"
309 fail "connect: network unreachable"
311 fail "connect: file descriptor passed instead of socket"
313 fail "connect: timed out without establishing connection"
315 fail ("connect: " ++ (errorCodeToStr errno))
318 writeVar status (Connected) `seqPrimIO`
323 The programmer must call $listen$ to tell the system software
324 that they are now interested in receiving data on this port. This
325 must be called on the bound socket before any calls to read or write
328 The programmer also gives a number which indicates the length of the
329 incoming queue of unread messages for this socket. On most systems the
330 maximum queue length is around 5. To remove a message from the queue
331 for processing a call to $accept$ should be made.
334 listen :: Socket -> -- Connected & Bound Socket
335 Int -> -- Queue Length
338 listen (MkSocket s family stype protocol status) backlog =
339 readVar status `thenST` \ currentStatus ->
340 if currentStatus /= Bound then
341 fail ("listen: can't peform listen on socket in status " ++
344 _ccall_ listen s backlog `thenPrimIO` \ result ->
346 getCErrorCode `thenPrimIO` \ errno ->
349 fail "listen: socket file descriptor invalid"
351 fail "listen: file descriptor is not a socket"
353 fail "listen: not supported fro this type of socket"
355 fail ("listen: " ++ (errorCodeToStr errno))
358 writeVar status (Listening) `seqPrimIO`
362 A call to $accept$ only returns when data is available on the given
363 socket, unless the socket has been set to non-blocking. It will
364 return a new socket which should be used to read the incoming data and
365 should then be closed. Using the socket returned by $accept$ allows
366 incoming requests to be queued on the original socket.
370 accept :: Socket -> -- Queue Socket
371 IO (Socket, -- Readable Socket
372 SockAddr) -- Peer details
374 accept sock@(MkSocket s family stype protocol status) =
375 readVar status `thenST` \ currentStatus ->
376 sIsAcceptable sock >>= \ okay ->
378 fail ("accept: can't peform accept on socket in status " ++
381 allocSockAddr family `thenPrimIO` \ (ptr, sz) ->
382 _casm_ ``%r = accept(%0,(struct sockaddr*)%1, &%2);''
383 s ptr sz `thenPrimIO` \ sock ->
385 getCErrorCode `thenPrimIO` \ errno ->
388 fail "accept: descriptor is invalid"
390 fail "accept: addr is not in writeable part of address space"
392 fail "accept: descriptor is not a socket"
394 fail ("accept: socket not of type" ++ show stype)
396 fail "accept: would block"
398 fail ("accept: " ++ (errorCodeToStr errno))
401 unpackSockAddr ptr `thenPrimIO` \ addr ->
402 newVar Connected `thenPrimIO` \ status ->
403 return ((MkSocket sock family stype protocol status), addr)
406 %************************************************************************
408 \subsection[Socket-DataPass]{Data Passing Primitives}
410 %************************************************************************
412 To allow Haskell to talk to C programs we need to beable to
413 communicate interms of byte streams. $writeSocket$ and
414 $readSocket$ should only be used for this purpose and not for
415 communication between Haskell programs. Haskell programs should use
416 the 1.3 IO hPutStr and associated machinery for communicating with
421 writeSocket :: Socket -> -- Connected Socket
422 String -> -- Data to send
423 IO Int -- Number of Bytes sent
425 writeSocket (MkSocket s family stype protocol status) xs =
426 readVar status `thenST` \ currentStatus ->
427 if not ((currentStatus /= Connected) || (currentStatus /= Listening)) then
428 fail ("writeSocket: can't peform write on socket in status " ++
431 _ccall_ write s xs (length xs) `thenPrimIO` \ nbytes ->
433 getCErrorCode `thenPrimIO` \ errno ->
436 fail "writeSocket: invalid file descriptor"
438 fail "writeSocket: disk quota exhausted"
440 fail "writeSocket: data area outside address space"
442 fail "writeSocket: max file size limit exeeded"
444 fail "writeSocket: interupt received before data written"
446 fail ("writeSocket: The stream is linked below a " ++
447 "multiplexor. The fd pointer was negative")
449 fail "writeSocket: no space left on device"
451 fail "writeSocket: hangup occured on stream"
453 fail "writeSocket: attempt to write to unopened pipe"
455 fail "writeSocket: to much data to write"
457 fail "writeSocket: would block"
459 fail "writeSocket: would block"
461 fail ("writeSocket: " ++ (errorCodeToStr errno))
466 readSocket :: Socket -> -- Connected Socket
467 Int -> -- Number of Bytes to Read
468 IO (String, Int) -- (Data Read, Number of Bytes)
470 readSocket (MkSocket s family stype protocol status) nbytes =
471 readVar status `thenST` \ currentStatus ->
472 if not ((currentStatus /= Connected) || (currentStatus /= Listening)) then
473 fail ("readSocket: can't perform read on socket in status " ++
476 -- newCharArray (0, nbytes) `thenPrimIO` \ ptr \ ->
477 _casm_ ``%r = (char*)malloc(1+sizeof(char)*%0);'' nbytes
478 `thenPrimIO` \ buffer ->
479 _ccall_ read s buffer nbytes `thenPrimIO` \ result ->
481 getCErrorCode `thenPrimIO` \ errno ->
484 fail "readSocket: no data to read (non-blocking)"
486 fail "readSocket: invalid file descriptor"
488 fail "readSocket: not a valid data message"
490 fail "readSocket: buffer outside allocated address space"
492 fail "readSocket: interupted by signal before data"
494 fail ("readSocket: The stream is linked below a " ++
495 "multiplexor. The file descriptor pointer was negative")
497 fail "readSocket: IO error"
499 fail "readSocket: descriptor is an NFS directory"
501 fail "readSocket: would block"
503 fail ("readSocket: " ++ (errorCodeToStr errno))
506 return (_unpackPS (_packCString buffer), result)
509 readSocketAll :: Socket -> IO String
513 readSocket s 4096 >>= \ (str, nbytes) ->
522 The port number the given socket is currently connected to can be
523 determined by calling $port$, is generally only useful when bind
524 was given $aNY\_PORT$.
527 socketPort :: Socket -> -- Connected & Bound Socket
528 IO Int -- Port Number of Socket
529 socketPort sock@(MkSocket s AF_INET stype protocol status) =
530 getSocketName sock >>= \ (SockAddrInet port _) ->
532 socketPort (MkSocket s family stype protocol status) =
533 fail ("socketPort: not supported for Family " ++ show family)
536 Calling $getPeerName$ returns the address details of the machine,
537 other than the local one, which is connected to the socket. This is
538 used in programs such as FTP to determine where to send the returning
539 data. The corresponding call to get the details of the local machine
543 getPeerName :: Socket -> IO SockAddr
544 getPeerName (MkSocket s family stype protocol status) =
545 allocSockAddr family `thenPrimIO` \ (ptr,sz) ->
546 _casm_ ``%r = getpeername(%0,(struct sockaddr*)%1,&%2);''
547 s ptr sz `thenPrimIO` \ result ->
549 getCErrorCode `thenPrimIO` \ errno ->
550 fail ("getPeerName: " ++ (errorCodeToStr errno))
552 unpackSockAddr ptr `thenPrimIO` \ addr ->
555 getSocketName :: Socket -> IO SockAddr
556 getSocketName (MkSocket s family stype protocol status) =
557 allocSockAddr family `thenPrimIO` \ (ptr,sz) ->
558 _casm_ ``%r = getsockname(%0,(struct sockaddr*)%1, &%2);''
559 s ptr sz `thenPrimIO` \ result ->
561 getCErrorCode `thenPrimIO` \ errno ->
562 fail ("getSocketName: " ++ (errorCodeToStr errno))
564 unpackSockAddr ptr `thenPrimIO` \ addr ->
569 %************************************************************************
571 \subsection[Socket-Properties]{Socket Properties}
573 %************************************************************************
596 sOL_SOCKET = ``SOL_SOCKET''
598 setSocketOptions :: Socket ->
600 SocketOption -> -- Option Name
601 String -> -- Option Value
604 getSocketOptons :: Socket ->
606 SocketOption -> -- Option Name
607 IO String -- Option Value
611 A calling sequence table for the main functions is shown in the table below.
615 \begin{tabular}{|l|c|c|c|c|c|c|c|}
617 {\bf A Call to} & socket & connect & bindSocket & listen & accept & read & write \\
619 {\bf Precedes} & & & & & & & \\
621 socket & & & & & & & \\
623 connect & + & & & & & & \\
625 bindSocket & + & & & & & & \\
627 listen & & & + & & & & \\
629 accept & & & & + & & & \\
631 read & & + & & + & + & + & + \\
633 write & & + & & + & + & + & + \\
636 \caption{Sequence Table for Major functions of Socket}
641 %************************************************************************
643 \subsection[Socket-OSDefs]{OS Dependent Definitions}
645 %************************************************************************
648 The following Family and Socket Type declarations were manually derived
649 from /usr/include/sys/socket.h on the appropriate machines.
651 Maybe a configure script that could parse the socket.h file to produce
652 the following declaration is required to make it ``portable'' rather than
653 using the dreaded \#ifdefs.
655 Presently only the following machine/os combinations are supported:
665 unpackFamily :: Int -> Family
666 packFamily :: Family -> Int
668 packSocketType :: SocketType -> Int
672 AF_UNSPEC -- unspecified
673 | AF_UNIX -- local to host (pipes, portals
674 | AF_INET -- internetwork: UDP, TCP, etc
675 | AF_IMPLINK -- arpanet imp addresses
676 | AF_PUP -- pup protocols: e.g. BSP
677 | AF_CHAOS -- mit CHAOS protocols
678 | AF_NS -- XEROX NS protocols
679 | AF_NBS -- nbs protocols
680 | AF_ECMA -- european computer manufacturers
681 | AF_DATAKIT -- datakit protocols
682 | AF_CCITT -- CCITT protocols, X.25 etc
684 | AF_DECnet -- DECnet
685 | AF_DLI -- Direct data link interface
687 | AF_HYLINK -- NSC Hyperchannel
688 | AF_APPLETALK -- Apple Talk
689 | AF_NIT -- Network Interface Tap
690 | AF_802 -- IEEE 80.2, also ISO 8802
691 | AF_OSI -- umberella of all families used by OSI
692 | AF_X25 -- CCITT X.25
694 | AF_GOSSIP -- US Government OSI
695 | AF_IPX -- Novell Internet Protocol
696 deriving (Eq, Ord, Ix, Text)
698 packFamily = index (AF_UNSPEC, AF_IPX)
699 unpackFamily family = (range (AF_UNSPEC, AF_IPX))!!family
706 AF_UNSPEC -- unspecified
707 | AF_UNIX -- local to host (pipes, portals)
708 | AF_INET -- internetwork: UDP, TCP, etc.
709 | AF_IMPLINK -- arpanet imp addresses
710 | AF_PUP -- pup protocols: e.g. BSP
711 | AF_CHAOS -- mit CHAOS protocols
712 | AF_NS -- XEROX NS protocols
713 | AF_ISO -- ISO protocols
714 | AF_ECMA -- european computer manufacturers
715 | AF_DATAKIT -- datakit protocols
716 | AF_CCITT -- CCITT protocols, X.25 etc
718 | AF_DECnet -- DECnet
719 | AF_DLI -- DEC Direct data link interface
721 | AF_HYLINK -- NSC Hyperchannel
722 | AF_APPLETALK -- Apple Talk
723 | AF_ROUTE -- Internal Routing Protocol
724 | AF_LINK -- Link layer interface
725 | Pseudo_AF_XTP -- eXpress Transfer Protocol (no AF)
726 | AF_NETMAN -- DNA Network Management
727 | AF_X25 -- X25 protocol
728 | AF_CTF -- Common Trace Facility
729 | AF_WAN -- Wide Area Network protocols
730 deriving (Eq, Ord, Ix, Text)
732 packFamily = index (AF_UNSPEC, AF_WAN)
733 unpackFamily family = (range (AF_UNSPEC, AF_WAN))!!family
744 deriving (Eq, Ord, Ix, Text)
746 packFamily = index (AF_UNSPEC, AF_IPX)
747 unpackFamily family = (range (AF_UNSPEC, AF_IPX))!!family
751 -- Alpha running OSF or a SPARC with SunOS, rather than Solaris.
753 #if __alpha__ || (sun && !__svr4__)
760 deriving (Eq, Ord, Ix, Text)
762 packSocketType stype = 1 + (index (Stream, SeqPacket) stype)
765 -- This is a Sun running Solaris rather than SunOS
775 deriving (Eq, Ord, Ix, Text)
777 packSocketType stype = 1 + (index (Datagram, SeqPacket) stype)
789 deriving (Eq, Ord, Ix, Text)
791 packSocketType stype = 1 + (index (Stream, Packet) stype)
795 %************************************************************************
797 \subsection[Socket-Util]{Utility Functions}
799 %************************************************************************
803 iNADDR_ANY = ``INADDR_ANY''::_Word
804 sOMAXCONN = ``SOMAXCONN''::Int
805 maxListenQueue = sOMAXCONN
807 -------------------------------------------------------------------------------
808 shutdown :: Socket -> Int -> IO ()
809 shutdown (MkSocket s family stype protocol status) t =
810 primIOToIO (_ccall_ shutdown s t)
812 -------------------------------------------------------------------------------
814 sClose :: Socket -> IO ()
815 sClose (MkSocket s family stype protocol status) =
816 primIOToIO (_ccall_ close s)
818 -------------------------------------------------------------------------------
820 inet_addr :: String -> HostAddress
821 inet_addr ipstr = unsafePerformPrimIO (_ccall_ inet_addr ipstr)
823 -------------------------------------------------------------------------------
825 inet_ntoa :: HostAddress -> String
826 inet_ntoa haddr = unsafePerformPrimIO (
827 _casm_ ``struct in_addr addr;
828 addr.s_addr = htonl(%0);
829 %r = inet_ntoa (addr);'' haddr `thenPrimIO` \ str ->
830 returnPrimIO (_unpackPS (_packCString str)))
832 -------------------------------------------------------------------------------
834 sIsConnected :: Socket -> IO Bool
835 sIsConnected (MkSocket s family stype protocol status) =
836 readVar status `thenST` \ value ->
837 return (value == Connected)
839 -------------------------------------------------------------------------------
841 sIsBound :: Socket -> IO Bool
842 sIsBound (MkSocket s family stype protocol status) =
843 readVar status `thenST` \ value ->
844 return (value == Bound)
846 -------------------------------------------------------------------------------
848 sIsListening :: Socket -> IO Bool
849 sIsListening (MkSocket s family stype protocol status) =
850 readVar status `thenST` \ value ->
851 return (value == Listening)
853 -------------------------------------------------------------------------------
855 sIsReadable :: Socket -> IO Bool
856 sIsReadable (MkSocket s family stype protocol status) =
857 readVar status `thenST` \ value ->
858 return (value == Listening || value == Connected)
860 -------------------------------------------------------------------------------
862 sIsWritable :: Socket -> IO Bool
863 sIsWritable = sIsReadable
865 -------------------------------------------------------------------------------
867 sIsAcceptable :: Socket -> IO Bool
868 sIsAcceptable (MkSocket s AF_UNIX Stream protocol status) =
869 readVar status `thenST` \ value ->
870 return (value == Connected || value == Bound || value == Listening)
871 sIsAcceptable (MkSocket s AF_UNIX _ protocol status) =
873 sIsAcceptable (MkSocket s _ stype protocol status) =
874 readVar status `thenST` \ value ->
875 return (value == Connected || value == Listening)
877 -------------------------------------------------------------------------------
880 sSetBlocking :: Socket -> Bool -> IO ()
881 sIsBlocking :: Socket -> IO Bool
884 -------------------------------------------------------------------------------
886 allocSockAddr :: Family -> PrimIO (_MutableByteArray _RealWorld Int, Int)
887 allocSockAddr AF_UNIX =
888 newCharArray (0,``sizeof(struct sockaddr_un)'') `thenPrimIO` \ ptr ->
890 (_,sz) = boundsOfByteArray ptr
892 returnPrimIO (ptr, sz)
893 allocSockAddr AF_INET =
894 newCharArray (0,``sizeof(struct sockaddr_in)'') `thenPrimIO` \ ptr ->
896 (_,sz) = boundsOfByteArray ptr
898 returnPrimIO (ptr, sz)
900 -------------------------------------------------------------------------------
902 unpackSockAddr :: _MutableByteArray _RealWorld Int -> PrimIO SockAddr
904 _casm_ ``%r = ((struct sockaddr*)%0)->sa_family;'' arr `thenPrimIO` \ fam ->
905 case unpackFamily fam of
906 AF_UNIX -> unpackSockAddrUnix arr
907 AF_INET -> unpackSockAddrInet arr
909 -------------------------------------------------------------------------------
911 unpackSockAddrUnix :: (_MutableByteArray _RealWorld Int) -> PrimIO SockAddr
912 unpackSockAddrUnix ptr =
913 _casm_ ``%r = ((struct sockaddr_un*)%0)->sun_path;'' ptr
914 `thenPrimIO` \ str ->
915 strcpy str `thenPrimIO` \ path ->
916 returnPrimIO (SockAddrUnix path)
918 -------------------------------------------------------------------------------
920 unpackSockAddrInet :: (_MutableByteArray _RealWorld Int) -> PrimIO SockAddr
921 unpackSockAddrInet ptr =
922 _casm_ ``%r = ntohs(((struct sockaddr_in*)%0)->sin_port);'' ptr
923 `thenPrimIO` \ port ->
924 _casm_ ``%r = ntohl(((struct sockaddr_in*)%0)->sin_addr.s_addr);'' ptr
925 `thenPrimIO` \ address ->
926 returnPrimIO (SockAddrInet port address)
928 -------------------------------------------------------------------------------
931 packSockAddr :: SockAddr -> PrimIO (_MutableByteArray _RealWorld Int)
932 packSockAddr (SockAddrUnix path) =
933 allocSockAddr AF_UNIX `thenPrimIO` \ (ptr,_) ->
934 _casm_ ``(((struct sockaddr_un *)%0)->sun_family) = AF_UNIX;''
935 ptr `thenPrimIO` \ () ->
936 _casm_ ``strcpy ((((struct sockaddr_un *)%0)->sun_path),%1);''
937 ptr path `thenPrimIO` \ () ->
940 packSockAddr (SockAddrInet port address) =
941 allocSockAddr AF_INET `thenPrimIO` \ (ptr,_) ->
942 _casm_ ``(((struct sockaddr_in *)%0)->sin_family) = AF_INET;''
943 ptr `thenPrimIO` \ () ->
944 _casm_ ``(((struct sockaddr_in *)%0)->sin_port) = htons((int)%1);''
945 ptr port `thenPrimIO` \ () ->
946 _casm_ ``(((struct sockaddr_in *)%0)->sin_addr.s_addr) = htonl(%1);''
947 ptr address `thenPrimIO` \ () ->
950 -------------------------------------------------------------------------------
952 socketToHandle :: Socket -> IO Handle
953 socketToHandle (MkSocket s family stype protocol status) =
954 _casm_ ``%r = fdopen (%0, "r+");'' s `thenPrimIO` \ ptr ->
955 newEmptyMVar >>= \ handle ->
956 putMVar handle (_SocketHandle ptr False) >>
959 -------------------------------------------------------------------------------