Skip to content

Loading…

Added raw pointer read/write operations #9

Merged
merged 1 commit into from

2 participants

@yav
yav commented

Hello,

I work at Galois Inc., and we've been using your binding to the open-ssl library. Thanks for your work! We noticed that the bytestring API for the 'read' and 'write' operations is a bit slow as it puts a lot of pressure on the garbage collector: receiving data requires allocation of temporary byte-string buffers, which are then parsed into actual Haskell values for further use.

I added a couple of functions to allow sending and receiving data directly to a memory buffer. This is useful because it makes it possible to reuse the same buffer for multiple operations, which leads to a significant gain in performance. The functions are analogous to 'hPutVuf' and 'hGetBufSome' from the 'System.IO' module.

Could you please merge the change and upload a new version to Hackage?

Thanks for your work,
-Iavor

@phonohawk phonohawk merged commit 7e6efe8 into phonohawk:master
@phonohawk
Owner

Great. Thank you very much for your contribution. I'll soon upload a new version to Hackage.

@phonohawk
Owner

http://hackage.haskell.org/package/HsOpenSSL-0.10.2
I'm proud of my package for being used by Galois ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 5, 2012
  1. @yav
Showing with 34 additions and 8 deletions.
  1. +1 −1 HsOpenSSL.cabal
  2. +33 −7 OpenSSL/Session.hsc
View
2 HsOpenSSL.cabal
@@ -15,7 +15,7 @@ Description:
encourages you to use and improve the tls package instead as long
as possible.
.
-Version: 0.10.1.4
+Version: 0.10.2
License: PublicDomain
License-File: COPYING
Author: Adam Langley, Mikhail Vorozhtsov, PHO, Taru Karttunen
View
40 OpenSSL/Session.hsc
@@ -34,8 +34,12 @@ module OpenSSL.Session
, tryConnect
, read
, tryRead
+ , readPtr
+ , tryReadPtr
, write
, tryWrite
+ , writePtr
+ , tryWritePtr
, lazyRead
, lazyWrite
, shutdown
@@ -444,6 +448,17 @@ tryRead ssl nBytes
WantWrite -> return (0, 0, WantWrite )
return $ bs <$ result
+-- | Read some data into a raw pointer buffer.
+-- Retrns the number of bytes read.
+readPtr :: SSL -> Ptr a -> Int -> IO Int
+readPtr ssl ptr len = sslBlock (\h -> tryReadPtr h ptr len) ssl
+
+-- | Try to read some data into a raw pointer buffer, without blocking.
+tryReadPtr :: SSL -> Ptr a -> Int -> IO (SSLResult Int)
+tryReadPtr ssl bufPtr nBytes =
+ fmap (fmap fromIntegral) (sslIOInner "SSL_read" _ssl_read (castPtr bufPtr) nBytes ssl)
+
+
foreign import ccall "SSL_write" _ssl_write :: Ptr SSL_ -> Ptr Word8 -> CInt -> IO CInt
-- | Write a given ByteString to the SSL connection. Either all the data is
@@ -456,13 +471,24 @@ tryWrite :: SSL -> B.ByteString -> IO (SSLResult ())
tryWrite ssl bs
| B.null bs = return $ SSLDone ()
| otherwise
- = B.unsafeUseAsCStringLen bs $ \(ptr, len) ->
- do result <- sslIOInner "SSL_write" _ssl_write ptr len ssl
- case result of
- SSLDone 0 -> ioError $ errnoToIOError "SSL_write" ePIPE Nothing Nothing
- SSLDone _ -> return $ SSLDone ()
- WantRead -> return WantRead
- WantWrite -> return WantWrite
+ = B.unsafeUseAsCStringLen bs $ \(ptr, len) -> tryWritePtr ssl ptr len
+
+-- | Send some data from a raw pointer buffer.
+writePtr :: SSL -> Ptr a -> Int -> IO ()
+writePtr ssl ptr len = sslBlock (\h -> tryWritePtr h ptr len) ssl >> return ()
+
+-- | Send some data from a raw pointer buffer, without blocking.
+tryWritePtr :: SSL -> Ptr a -> Int -> IO (SSLResult ())
+tryWritePtr ssl ptr len =
+ do result <- sslIOInner "SSL_write" _ssl_write (castPtr ptr) len ssl
+ case result of
+ SSLDone 0 -> ioError $ errnoToIOError "SSL_write" ePIPE Nothing Nothing
+ SSLDone _ -> return $ SSLDone ()
+ WantRead -> return WantRead
+ WantWrite -> return WantWrite
+
+
+
-- | Lazily read all data until reaching EOF. If the connection dies
-- without a graceful SSL shutdown, an exception is raised.
Something went wrong with that request. Please try again.