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:
|
instead to using a simple custom protocol something like:
|
||||||
|
|
||||||
> AUTH $localuuid $token
|
> AUTH $localuuid $token
|
||||||
< AUTH-OK $remoteuuid
|
< AUTH-SUCCESS $remoteuuid
|
||||||
> SENDPACK $length
|
> SENDPACK $length
|
||||||
> $gitdata
|
> $gitdata
|
||||||
< RECVPACK $length
|
< RECVPACK $length
|
||||||
< $gitdata
|
< $gitdata
|
||||||
> GET $pos $key
|
> GET $pos $key
|
||||||
< SENDING $length
|
< DATA $length
|
||||||
< $bytes
|
< $bytes
|
||||||
> GET-OK
|
> SUCCESS
|
||||||
> PUT $key
|
> PUT $key
|
||||||
< SEND $pos
|
< PUT-FROM $pos
|
||||||
> SENDING $length
|
> DATA $length
|
||||||
> $bytes
|
> $bytes
|
||||||
< PUT-OK
|
< SUCCESS
|
||||||
|
|
||||||
Today's work was sponsored by Riku Voipio.
|
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