Giter Site home page Giter Site logo

zyreapps / hydra Goto Github PK

View Code? Open in Web Editor NEW
55.0 23.0 16.0 1.33 MB

The Hydra Protocol

License: Mozilla Public License 2.0

CMake 1.89% QMake 0.98% Prolog 0.28% C++ 9.74% QML 9.28% Shell 6.03% Ruby 8.47% Makefile 0.34% C 42.67% Clojure 5.52% Java 14.80%

hydra's Introduction

# Hydra

Build Status

## Contents

Building Hydra

Building Hydra QML app

Testing

Overview

The Hydra Data Model

The Hydra Protocol โ€ƒNode Discovery โ€ƒPost Synchronization

The Hydra API

Implementation Notes

Ownership and Contributing

## Building Hydra

To build the Hydra C stack do the following:

git clone git://github.com/zeromq/libzmq.git
git clone git://github.com/zeromq/czmq.git
git clone git://github.com/zeromq/zyre.git
git clone git://github.com/edgenet/hydra.git
for project in libzmq czmq zyre hydra; do
    cd $project
    ./autogen.sh && ./configure && make check
    sudo make install && ldconfig
    cd ..
done
## Building Hydra QML app

For documentation on building the QML app, see the README.md under the app/ subdirectory.

## Testing

To test from the command line, run the hydrad executable like this:

hydrad -t       #  Create some test posts
hydrad          #  Run a node in default .hydra directory
hydrad node1    #  Run a node in ./node1 directory (creates it if needed)
hydrad -i ...   #  Use IPC, if you don't have WiFi/LAN enabled
hydrad -v ...   #  Enable verbose animation / tracing

Note -i option needs at least one node to run using default .hydra directory.

## Overview

Hydra is a simple protocol and stack for opportunistic sharing of events and content.

The goal of the Hydra project is to explore and learn how to share knowledge and information across short-lived wireless networks between mobile users. Hydra exploits "proximity networks", that is the physical closeness of individuals. The Hydra project is part of the edgenet experiment to design and build decentralized networks, with no dependency on broadband Internet nor centralized services.

Plausibly, Hydra could evolve into a fully decentralized social network, closely mapping and amplifying existing human protocols for knowledge and information sharing. However at this stage, Hydra is simply a model for exchanging cat photos.

Hydra does make some core assumptions about technology and platform. It assumes that:

  • The platform is a mobile smartphone or tablet, probably running Android;
  • Connectivity is wireless, TCP and UDP over WiFi.
  • Peers discover and talk to each other opportunistically, as individuals move around.

Not that Hydra is not a mesh network and does no forwarding or routing. This is deliberate. We assume that peers move around too rapidly for routing knowledge to ever be valid. All a peer can ever know is "I can talk to this other peer, for now."

Hydra is aimed, in its current incarnation, at technical conferences, weddings, parties, and funerals. The participants are in rough proximity, for a period of hours or days. They share a strong set of interests. They implicitly trust each other, yet do not care about identities. They mainly want to share photos and comments on photos.

## The Hydra Data Model

This section describes the Hydra Data model, which underpins the rest of the design.

A Hydra network consists of a set of self-identified nodes, which produce and share posts. A post is a piece of content (typically a photo or some text) with metadata.

Every node has a self-generated UUID. The node configuration is held in hydra.cfg, which has this format:

hydra
    identity = "FB04239C786E480BB27007576627C502"
    nickname = "Anonymous"

//TODO: instead of a UUID, generate a CURVE certificate and use the public key as node ID. Then, we can sign posts with our certificate to ensure authenticity.//

Posts have a permanent unique identifier which is the SHA1 digest of the post metadata, calculated thus:

post_id = sha1 (subject ":" timestamp ":" parent_id ":" mime_type ":" digest)

A post has these immutable properties, apart from its identifier:

  • A subject line (a long string).
  • The creation timestamp, in ISO 8601 UTC format: yyyy-mm-ddThh:mm:ssZ
  • An optional parent post ID, allowing posts to be nested by a presentation layer.
  • The MIME type (e.g. "image/jpg") of the content.
  • The SHA1 digest of the content.
  • The content size, zero or greater.
  • The content itself, zero or more octets.

When a post is held by multiple nodes, it shall have the same ID on all nodes.

Every post has a content of zero or more octets. Hydra does not support multipart contents.

//TODO: extend to support multiple content parts.//

A Hydra node can store posts and content in any format. That is, the protocol makes no assumptions about the storage model.

## The Hydra Protocol

This section describes the Hydra Protocol, which governs how two nodes exchange state.

The Hydra protocol is optimized for WiFi connections and prioritizes bandwidth and reliability over latency. So it is chatty, and does not try to push data opportunistically towards peers.

The protocol is asymmetric, with a "client" fetching posts from a "server". In practice, when two nodes discover each other, they will each act as client to each other's server. That is, a Hydra node runs one server, and N clients, at any point in time.

### Node Discovery

Hydra uses Zyre (UDP broadcast beacons) for node discovery, using a Zyre header "X-HYDRA", which provides the server's public TCP endpoint.

### Post Synchronization

We assume that it is usually impossible to fetch all posts from a peer, within any given window of opportunity. Thus, Hydra aims to fetch the most interesting posts from a peer. The handshake between the client and the server works as follows:

  • The client says HELLO, and the server replies with HELLO-OK, giving both nodes the chance to identify each other.

  • The client tells the server what range of posts it already has for the server. If the server is unknown to the client, or has never sent it any posts, this range is empty. Otherwise it consists of two post IDs, an "oldest" and a "newest".

  • The server replies with the number of posts it can offer the client, both newer than the range, and older than the range.

  • The client can then request posts, always extending the range either towards newer posts, or towards older posts.

  • Since posts can exist across many servers, clients first fetch the post ID metadata, and then fetch the content as desired.

  • Clients fetch content on a chunk-by-chunk basis. This prevents memory overflow when sending large files.

  • The client can also decide to start from scratch and request the newest posts from the server, if the gap is too large.

The following ABNF grammar defines the The Hydra Protocol:

hydra = hello *( get-post ) [ goodbye ]
hello = c:hello ( s:hello-ok / s:invalid / s:failed )
get-post = c:get-post ( s:get-post-ok / s:invalid / s:failed )
goodbye = c:goodbye ( s:goodbye-ok / s:invalid / s:failed )

;  Open new connection, provide client credentials.                      

HELLO           = signature %d1 identity nickname
signature       = %xAA %xA0             ; two octets
identity        = string                ; Client identity
nickname        = string                ; Client nickname

;  Accept new connection, provide server credentials.                    

HELLO-OK        = signature %d2 identity nickname
identity        = string                ; Server identity
nickname        = string                ; Server nickname

;  Client requests next post that is older than the specified post ID. If
;  the post ID is "HEAD", fetches the newest post that the server has.   

NEXT-OLDER      = signature %d3 ident
ident           = string                ; Client's oldest post ID

;  Client requests next post that is newer than the specified post ID. If
;  the post ID is "TAIL", fetches the oldest post that the server has.   

NEXT-NEWER      = signature %d4 ident
ident           = string                ; Client's newest post ID

;  Server returns a post identity to the client. This command does not   
;  provide all metadata, only the post identity string. Clients can then 
;  filter out posts they already have.                                   

NEXT-OK         = signature %d5 ident
ident           = string                ; Post identifier

;  Server signals that it has no (more) posts for the client.            

NEXT-EMPTY      = signature %d6

;  Client requests the metadata for the current post. A META command only
;  makes sense after a NEXT-OLDER or NEXT-NEWER with a successful NEXT-OK
;  from the server.                                                      

META            = signature %d7

;  Server returns the metadata for the current post (as returned by      
;  NEXT-OK).                                                             

META-OK         = signature %d8 subject timestamp parent_id digest mime_type content_size
subject         = longstr               ; Subject line
timestamp       = string                ; Post creation timestamp
parent id       = string                ; Parent post ID, if any
digest          = string                ; Content SHA1 digest
mime type       = string                ; Content MIME type
content size    = number-8              ; Content size, octets

;  Client fetches a chunk of content data from the server, for the       
;  current post (as returned by NEXT-OK).                                

CHUNK           = signature %d9 offset octets
offset          = number-8              ; Chunk offset in file
octets          = number-4              ; Maximum chunk size to fetch

;  Return a chunk of post content.                                       

CHUNK-OK        = signature %d10 offset content
offset          = number-8              ; Chunk offset in file
content         = chunk                 ; Content data chunk

;  Close the connection politely                                         

GOODBYE         = signature %d11

;  Handshake a connection close                                          

GOODBYE-OK      = signature %d12

;  Command failed for some specific reason                               

ERROR           = signature %d13 status reason
status          = number-2              ; 3-digit status code
reason          = string                ; Printable explanation

; A chunk has 4-octet length + binary contents
chunk           = number-4 *OCTET

; Strings are always length + text contents
string          = number-1 *VCHAR
longstr         = number-4 *VCHAR

; Numbers are unsigned integers in network byte order
number-1        = 1OCTET
number-2        = 2OCTET
number-4        = 4OCTET
number-8        = 8OCTET
## The Hydra API

This section describes the API provided by the current Hydra implementation, and is meant for developers who wish to use Hydra in their applications.

TBD.

## Implementation Notes

A Hydra service runs in a working directory and uses a lockfile (hydra.lock) to prevent multiple instances from running in the same directory.

This Hydra implementation stores posts in a subdirectory called posts, with one text file per post, in ZPL format (ZeroMQ RFC 4). Post files are named "yyyy-mm-dd(nnnnnnnnn)", consisting of the date the post was created on disk (not the post timestamp), and a 9-digit sequence number (the most decimal digits that will fit into a 32-bit integer).

The Hydra working directory has these files:

  • hydra.cfg -- a configuration file, generated the first time if needed.
  • posts/ -- a subdirectory holding all posts.
  • peers/ -- a subdirectory holding peer status files. A peer status file is named by the peer's unique ID and holds the peer meta data in SPL format.
## Ownership and Contributing

The contributors are listed in AUTHORS. This project uses the MPL v2 license, see LICENSE.

The contribution policy is the standard ZeroMQ C4.1 process. Please read this RFC if you have never contributed to a ZeroMQ project.

Hydra uses the CLASS (C Language Style for Scalabilty) guide for code style.

To report an issue, use the Hydra issue tracker at github.com.

hydra's People

Contributors

c-rack avatar hintjens avatar ifesdjeen avatar jemc avatar lukebond avatar mknoszlig avatar noemie avatar taotetek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hydra's Issues

Compilation error on OS/X

In preparation for 0MQ training at FOSDEM I'm installing the hydra stack. I get the following error during make check for hydra after following the installation instructions in the main README:

lbond@Lukes-MacBook-Air /Users/lbond/Development/hydra (master)
$ make check
Making check in doc
make[1]: Nothing to be done for `check'.
  CC       src/src_libhydra_la-hydra.lo
src/hydra.c:55:36: error: comparison of constant -1 with expression of type 'mode_t' (aka 'unsigned short') is always false
      [-Werror,-Wtautological-constant-out-of-range-compare]
    if (zsys_file_mode (directory) == -1)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~
1 error generated.
make[1]: *** [src/src_libhydra_la-hydra.lo] Error 1
make: *** [check-recursive] Error 1

Is there an extra step required to build on OS/X or is it not currently possible?

Problem: hydra_fetch does not fetch local files

We need a way for the application to receive existing posts we already have if we intend to view them. I don't know if we want to expand the scope of hydra_fetch to also fetch local posts as well as remote ones, or if we need to add another method for fetching local posts into the application for viewing.

Problem: No API for opening a `hydra_ledger` in the right directory.

Looking at the hydra_ledger class, it looks like the directory must be set via zsys_dir_change, which is not exposed in the wrappable modelled API. We need some way to make sure the ledger gets opened in the right directory.

Ideally, I'd like to not have to specify the directory again if I've already given it to my instance of the hydra class in hydra_new.

Proposed solution: Add the hydra_make_ledger method that will create and return a "fresh" hydra_ledger that was hydra_ledger_loaded in the right directory. This way, all I have to do is get a ledger from the main hydra instance, fetch all the posts from it, and destroy the ledger.

If this sounds right, I don't mind adding it myself.

Problem: After some time idle, zlistx assertion failure

After some time of being idle (no new posts crossing back and forth between hydras), I see a zlistx assertion failure, often at the same time on both hydras.

Here is the backtrace for all threads given by gdb:

[...]
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=3ED52811BADAD955626F691EFF6A493D3EC4701B
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=6073F47541E7A7FAF79A3383126842F322FF38AC
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=EC6CB4F4ABB06EB3027BDC826E135E4CFC5A5343
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=A5ACC41151AA0C88E7F711C390E48D202EB2D14A
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=51571C4BF60759E4780E5870F70EDD1C36FFC27C
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=C284FC29F5A2742F1F310C90A20DAFF580FE0092
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=993998CA98722B45395694E59BDF0FF8FF19F574
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=BCBE761DF7DE6665CDBCD91898C6CFC31D877A61
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=F70AEAD5C538726ADA4C02C2C8B7B029C0A3FAEF
W: 15-01-28 01:49:44 hydra_ledger: store post, ident=87AF476DCCBC9E064AA699C2BDF6C2B7469ED019
hydrad: src/zlistx.c:351: zlistx_detach: Assertion `node->tag == 0x0006cafe' failed.

Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff5693700 (LWP 18930)]
0x0000003f34e35877 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.18-16.fc20.x86_64 libgcc-4.8.3-7.fc20.x86_64 libstdc++-4.8.3-7.fc20.x86_64 libuuid-2.24.2-1.fc20.x86_64
(gdb) thread apply all bt

Thread 9 (Thread 0x7fffdf7fe700 (LWP 19266)):
#0  0x0000003f34eea71d in poll () from /lib64/libc.so.6
#1  0x00007ffff76e7c3d in zmq_poll (items_=0x7fffd4002700, nitems_=3, timeout_=timeout_@entry=3600000)
    at src/zmq.cpp:746
#2  0x00007ffff79289b7 in zloop_start (self=0x7fffd40019b0) at src/zloop.c:731
#3  0x00007ffff7dce3ba in hydra_client (cmdpipe=0x7ffff0028fe0, msgpipe=0x7ffff00217a0)
    at ./src/hydra_client_engine.inc:1314
#4  0x00007ffff7912e53 in s_thread_shim (args=0x7ffff0028fc0) at src/zactor.c:67
#5  0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#6  0x0000003f34ef4b8d in clone () from /lib64/libc.so.6

Thread 8 (Thread 0x7fffdffff700 (LWP 19057)):
#0  0x0000003f34eea71d in poll () from /lib64/libc.so.6
#1  0x00007ffff76e7c3d in zmq_poll (items_=0x7fffd8002700, nitems_=3, timeout_=timeout_@entry=3600000)
    at src/zmq.cpp:746
#2  0x00007ffff79289b7 in zloop_start (self=0x7fffd80019b0) at src/zloop.c:731
#3  0x00007ffff7dce3ba in hydra_client (cmdpipe=0x7ffff001a010, msgpipe=0x7ffff0018790)
    at ./src/hydra_client_engine.inc:1314
#4  0x00007ffff7912e53 in s_thread_shim (args=0x7ffff0019ff0) at src/zactor.c:67
#5  0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#6  0x0000003f34ef4b8d in clone () from /lib64/libc.so.6

---Type <return> to continue, or q <return> to quit---
Thread 7 (Thread 0x7ffff4c66700 (LWP 18931)):
#0  0x0000003f34eea71d in poll () from /lib64/libc.so.6
#1  0x00007ffff76e7c3d in zmq_poll (items_=items_@entry=0x7ffff4c65e30, nitems_=2, timeout_=1000) at src/zmq.cpp:746
#2  0x00007ffff791790d in zbeacon (pipe=<optimized out>, args=<optimized out>) at src/zbeacon.c:294
#3  0x00007ffff7912e53 in s_thread_shim (args=0x7fffe8003670) at src/zactor.c:67
#4  0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#5  0x0000003f34ef4b8d in clone () from /lib64/libc.so.6

Thread 6 (Thread 0x7ffff5693700 (LWP 18930)):
#0  0x0000003f34e35877 in raise () from /lib64/libc.so.6
#1  0x0000003f34e36f68 in abort () from /lib64/libc.so.6
#2  0x0000003f34e2e7d6 in __assert_fail_base () from /lib64/libc.so.6
#3  0x0000003f34e2e882 in __assert_fail () from /lib64/libc.so.6
#4  0x00007ffff79266b3 in zlistx_detach (self=self@entry=0x7fffec0024e0, handle=<optimized out>) at src/zlistx.c:351
#5  0x00007ffff79266f2 in zlistx_delete (self=0x7fffec0024e0, handle=<optimized out>) at src/zlistx.c:377
#6  0x00007ffff7928aad in zloop_start (self=0x7fffec0022b0) at src/zloop.c:765
#7  0x00007ffff7dcb08a in hydra_server (pipe=0x7ffff00096b0, args=0x0) at ./src/hydra_server_engine.inc:1027
#8  0x00007ffff7912e53 in s_thread_shim (args=0x7ffff00096f0) at src/zactor.c:67
#9  0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003f34ef4b8d in clone () from /lib64/libc.so.6

Thread 5 (Thread 0x7ffff5e94700 (LWP 18929)):
#0  0x0000003f34eea71d in poll () from /lib64/libc.so.6
---Type <return> to continue, or q <return> to quit---
#1  0x00007ffff76e7c3d in zmq_poll (items_=0x7fffe8005060, nitems_=3, timeout_=timeout_@entry=1000) at src/zmq.cpp:746
#2  0x00007ffff792ce88 in zpoller_wait (self=0x7fffe80011b0, timeout=1000) at src/zpoller.c:145
#3  0x00007ffff7bab721 in zyre_node_actor (pipe=<optimized out>, args=<optimized out>) at src/zyre_node.c:851
#4  0x00007ffff7912e53 in s_thread_shim (args=0x7ffff00019c0) at src/zactor.c:67
#5  0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#6  0x0000003f34ef4b8d in clone () from /lib64/libc.so.6

Thread 4 (Thread 0x7ffff6695700 (LWP 18928)):
#0  0x0000003f34eea71d in poll () from /lib64/libc.so.6
#1  0x00007ffff76d0d4a in zmq::signaler_t::wait (this=this@entry=0x7ffff00213e0, timeout_=timeout_@entry=-1)
    at src/signaler.cpp:205
#2  0x00007ffff76bd080 in zmq::mailbox_t::recv (this=this@entry=0x7ffff0021380, cmd_=cmd_@entry=0x7ffff6694a70, 
    timeout_=-1) at src/mailbox.cpp:70
#3  0x00007ffff76d1e36 in zmq::socket_base_t::process_commands (this=this@entry=0x7ffff0020fc0, 
    timeout_=<optimized out>, throttle_=throttle_@entry=false) at src/socket_base.cpp:980
#4  0x00007ffff76d24fb in zmq::socket_base_t::recv (this=this@entry=0x7ffff0020fc0, msg_=msg_@entry=0x7ffff6694b00, 
    flags_=flags_@entry=0) at src/socket_base.cpp:912
#5  0x00007ffff76e7519 in s_recvmsg (s_=s_@entry=0x7ffff0020fc0, msg_=msg_@entry=0x7ffff6694b00, 
    flags_=flags_@entry=0) at src/zmq.cpp:446
#6  0x00007ffff76e771a in zmq_msg_recv (msg_=msg_@entry=0x7ffff6694b00, s_=s_@entry=0x7ffff0020fc0, 
    flags_=flags_@entry=0) at src/zmq.cpp:590
#7  0x00007ffff76e772e in zmq_recvmsg (s_=s_@entry=0x7ffff0020fc0, msg_=msg_@entry=0x7ffff6694b00, 
    flags_=flags_@entry=0) at src/zmq.cpp:455
---Type <return> to continue, or q <return> to quit---
#8  0x00007ffff7939b1d in zstr_recv (source=<optimized out>) at src/zstr.c:67
#9  0x00007ffff7dcf373 in s_accept_reply (self=0x7ffff0011300) at ./src/hydra_client_engine.inc:1435
#10 0x00007ffff7dcf063 in hydra_client_destructor (self=0x7ffff0011300) at ./src/hydra_client_engine.inc:1500
#11 0x00007ffff7dcef6d in hydra_client_destroy (self_p=0x7ffff6694e08) at ./src/hydra_client_engine.inc:1385
#12 0x00007ffff7dc58b1 in s_self_handle_zyre (self=0x7ffff00008c0) at src/hydra.c:493
#13 0x00007ffff7dc4c7b in s_self_actor (pipe=0x603070, args=0x401312) at src/hydra.c:540
#14 0x00007ffff7912e53 in s_thread_shim (args=0x603050) at src/zactor.c:67
#15 0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#16 0x0000003f34ef4b8d in clone () from /lib64/libc.so.6

Thread 3 (Thread 0x7ffff6e96700 (LWP 18927)):
#0  0x0000003f34ef5163 in epoll_wait () from /lib64/libc.so.6
#1  0x00007ffff76b94b6 in zmq::epoll_t::loop (this=0x605bc0) at src/epoll.cpp:146
#2  0x00007ffff76e1e80 in thread_routine (arg_=0x605c40) at src/thread.cpp:86
#3  0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#4  0x0000003f34ef4b8d in clone () from /lib64/libc.so.6

Thread 2 (Thread 0x7ffff7697700 (LWP 18926)):
#0  0x0000003f34ef5163 in epoll_wait () from /lib64/libc.so.6
#1  0x00007ffff76b94b6 in zmq::epoll_t::loop (this=0x605740) at src/epoll.cpp:146
#2  0x00007ffff76e1e80 in thread_routine (arg_=0x6057c0) at src/thread.cpp:86
#3  0x0000003f35207ee5 in start_thread () from /lib64/libpthread.so.0
#4  0x0000003f34ef4b8d in clone () from /lib64/libc.so.6
---Type <return> to continue, or q <return> to quit---

Thread 1 (Thread 0x7ffff76997c0 (LWP 18921)):
#0  0x0000003f34ebc6ed in nanosleep () from /lib64/libc.so.6
#1  0x0000003f34ebc584 in sleep () from /lib64/libc.so.6
#2  0x0000000000401099 in main (argc=1, argv=0x7fffffffddc8) at src/hydrad.c:102
(gdb)

Problem: No logo image.

I don't want to get too fancy with the graphics for the first iteration of the QML application for this FOSDEM 2015, as we don't have much time to prepare, but it would be nice to at least have a basic logo for a splash screen and to demonstrate how image posts look and behave in Hydra.

I'm not very graphically-inclined, so I'm hoping someone else will step up and want to give us a logo image. Ideally, it would go well with the android "Holo Dark" theme (see http://developer.android.com/design/style/themes.html). Something minimal and vector-based sounds nice to me, but I'll leave the graphic design up to those who are good at it.

We should avoid using content that would bring us undue copyright encumberment - if you do graphics work you probably know what this entails better than I do.

Problem: `ACCESS_REFUSED` on `hydra_store_string`

When I try to run hydra_store_string to add a post:

I: 15-01-27 18:00:00 hydrad: store new post filename=2015-01-27(00000020) bytes=0
D: 15-01-27 18:00:00 check_status_code: 401
W: 15-01-27 18:00:00 hydra_ledger: store post, ident=20964C1DC96537FB613532FF6D43358A1596BFA2
E: 15-01-27 18:00:00 hydra: failed - Unhandled error

The debug statement called check_status_code is one I added temporarily to print the hydra proto status code. Code 401 is HYDRA_PROTO_ACCESS_REFUSED, which is sent by hydra_server in the check_if_client_has_credit action when the client's credit drops to zero. So it looks like the hydra_client FSM is not sending credit when it needs to.

Problem: SIGSEGV in hydra_post_dup

SIGSEGV when trying to strdup self->location when it is NULL.
https://github.com/edgenet/hydra/blob/master/src/hydra_post.c#L422

This happens anytime I try to run two instances of hydrad on my local machine where one or both of them has posts to share.

I see from reading other parts of the code that some code paths leave self->location as NULL, but I'm not entirely sure of the intention here to know what kind of guard we need - an assertion that it isn't NULL, or to leave copy-location as NULL.

Problem: Client expires and terminates after one second.

When I start up two hydrad instances with posts, they find eachother and exchange posts. After all the posts are exchanged, both clients expire and time out after one second of inactivity. Based on the recommended heartbeat setup described in the zproto README, It seems like they should be PINGing instead of terminateing on an expired_event event, but I don't want to make this change without first asking if there's some other technique employed by this FSM design that I'm missing.

[...]
D: 15-01-25 10:46:44 hydra_client: scanning forwards:
D: 15-01-25 10:46:44 hydra_client:      NEXT_OK
D: 15-01-25 10:46:44 hydra_client:          $ use this post as newest
D: 15-01-25 10:46:44 hydra_client:          $ skip post if duplicate
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=8C2C95C0AF980685F08F4D1587728151694CD8CE
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=5D40EBE896ABD607B511791894E163DC2165E2B5
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=3CAA5898C79B5DEC2844E2CB71910E968C5C48A1
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=780166A5E0B60F2DFF33C25F9A62B3399D4E48A4
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=0DA894A01C3490BC00C040F6DABB73C8287C28F1
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=AEA3B8E33EE9AD7057CF197C06864AFA95E7784D
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=A2E9EFE4F96090D20910B11BB2D41D7792C46C1D
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=458D1EBFB7C4C6727E18A0DD4953BE5899FA6A99
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=B76BD986C4D65F0200BF8C25BF56001E677ED523
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=8210C08D56B15E6C958863C4DCF32CB831FCCAD7
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=960A908F8FCF5803B622210AF39A7A8383B49E6A
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=0BCAC9AD7013A1B85EEE9F89164ECC554A1001D3
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=484671DC42F6C52C660F49C1FB834FC3B11320F5
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=B45EEB02E1277C1579F01B6A6B53381A3D05F4F4
W: 15-01-25 10:46:44 hydra_ledger: store post, ident=BC5EFD039D353E08E87A32B7A7D3C2F423F22B42
D: 15-01-25 10:46:44 hydra_client:          ! duplicate
D: 15-01-25 10:46:44 hydra_client: scanning forwards:
D: 15-01-25 10:46:44 hydra_client:      duplicate
D: 15-01-25 10:46:44 hydra_client:          $ send NEXT_NEWER
D: 15-01-25 10:46:44 hydra_client:          > scanning forwards
D: 15-01-25 10:46:44 hydra_client: scanning forwards:
D: 15-01-25 10:46:44 hydra_client:      NEXT_EMPTY
D: 15-01-25 10:46:44 hydra_client:          $ prepare to fetch older post
D: 15-01-25 10:46:44 hydra_client:          $ send NEXT_OLDER
D: 15-01-25 10:46:44 hydra_client:          > scanning backwards
D: 15-01-25 10:46:44 hydra_client: scanning backwards:
D: 15-01-25 10:46:44 hydra_client:      NEXT_EMPTY
D: 15-01-25 10:46:44 hydra_client:          $ signal sync success
D: 15-01-25 10:46:44 hydra_client:          > connected
D: 15-01-25 10:46:45 hydra_client: connected:
D: 15-01-25 10:46:45 hydra_client:      expired
D: 15-01-25 10:46:45 hydra_client:          $ signal server not present
D: 15-01-25 10:46:45 hydra_client:          $ terminate
D: 15-01-25 10:46:45 hydra_client:          > connected
E: 15-01-25 10:46:45 hydra: failed - Server is not reachable

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.