devblog
This commit is contained in:
parent
6a5592c05f
commit
f3ea75a74c
2 changed files with 57 additions and 6 deletions
|
@ -45,19 +45,19 @@ authentication. Which is a whole nother ball of complexity. So, I'm leaning
|
|||
instead to using a simple custom protocol something like:
|
||||
|
||||
> AUTH $localuuid $token
|
||||
< AUTH-OK $remoteuuid
|
||||
< AUTH-SUCCESS $remoteuuid
|
||||
> SENDPACK $length
|
||||
> $gitdata
|
||||
< RECVPACK $length
|
||||
< $gitdata
|
||||
> GET $pos $key
|
||||
< SENDING $length
|
||||
< DATA $length
|
||||
< $bytes
|
||||
> GET-OK
|
||||
> SUCCESS
|
||||
> PUT $key
|
||||
< SEND $pos
|
||||
> SENDING $length
|
||||
< PUT-FROM $pos
|
||||
> DATA $length
|
||||
> $bytes
|
||||
< PUT-OK
|
||||
< SUCCESS
|
||||
|
||||
Today's work was sponsored by Riku Voipio.
|
||||
|
|
51
doc/devblog/day_427__free_p2p.mdwn
Normal file
51
doc/devblog/day_427__free_p2p.mdwn
Normal file
|
@ -0,0 +1,51 @@
|
|||
For a Haskell programmer, and day where a big thing is implemented
|
||||
without the least scrap of code that touches the IO monad is a good day.
|
||||
And this was a good day for me!
|
||||
|
||||
Implemented the p2p protocol for tor hidden services. Its needs are somewhat
|
||||
similar to the external special remote protocol, but the two protocols are
|
||||
not fully overlapping with one-another. Rather than try to unify them, and
|
||||
so complicate both cases, I prefer to reuse as much code as possible between
|
||||
separate protocol implementations. The generating and parsing of messages
|
||||
is largely shared between them. I let the new p2p protocol otherwise
|
||||
develop in its own direction.
|
||||
|
||||
But, I *do* want to make this p2p protocol reusable for other types of p2p
|
||||
networks than tor hidden services. This was an opportunity to use the Free
|
||||
monad, which I'd never used before. It worked out great, letting me write
|
||||
monadic code to handle requests and responses in the protocol, that reads
|
||||
the content of files and resumes transfers and so on, all independent
|
||||
of any concrete implementation.
|
||||
|
||||
The whole implementation of the protocol only needed 74 lines of monadic code.
|
||||
It helped that I was able to factor out functions like this one, that is used
|
||||
both for handling a download, and by the remote when an upload is sent to it:
|
||||
|
||||
receiveContent :: Key -> Offset -> Len -> Proto Bool
|
||||
receiveContent key offset len = do
|
||||
content <- receiveBytes len
|
||||
ok <- writeKeyFile key offset content
|
||||
sendMessage $ if ok then SUCCESS else FAILURE
|
||||
return ok
|
||||
|
||||
To get transcripts of the protocol in action, the Free monad can be evaluated
|
||||
purely, providing the other side of the conversation:
|
||||
|
||||
ghci> putStrLn $ protoDump $ runPure (put (fromJust $ file2key "WORM--foo")) [PUT_FROM (Offset 10), SUCCESS]
|
||||
> PUT WORM--foo
|
||||
< PUT-FROM 10
|
||||
> DATA 90
|
||||
> bytes
|
||||
< SUCCESS
|
||||
result: True
|
||||
|
||||
ghci> putStrLn $ protoDump $ runPure (serve (toUUID "myuuid")) [GET (Offset 0) (fromJust $ file2key "WORM--foo")]
|
||||
< GET 0 WORM--foo
|
||||
> PROTO-ERROR must AUTH first
|
||||
result: ()
|
||||
|
||||
Am very happy with all this pure code and that I'm finally using Free monads.
|
||||
Next I need to get down the the dirty business of wiring this up to
|
||||
actual IO actions, and an actual network connection.
|
||||
|
||||
Today's work was sponsored by Jake Vosloo on Patreon.
|
Loading…
Add table
Reference in a new issue