void Node_add_sib(Node *sib1, Node *sib2) { assert_not(sib1, NULL); assert_not(sib2, NULL); LIST_ADD(Node, sib1, sib2, sibling); sib2->parent = sib1->parent; }
void Node_add_child(Node *parent, Node *child) { assert_not(parent, NULL); assert_not(child, NULL); LIST_ADD(Node, parent->child, child, sibling); child->parent = parent; }
void Node_name(Node *node, bstring name) { assert_not(node, NULL); assert_not(name, NULL); if(node->name) { bdestroy(node->name); } node->name = name; }
void Hub_broadcast(Hub *hub, Message *msg) { Member *te = NULL; struct sglib_Member_iterator it; assert_not(msg, NULL); assert_not(hub, NULL); dbg("BROADCASTING MESSAGE:"); Message_dump(msg); for(te=sglib_Member_it_init(&it,hub->members); te!=NULL; te=sglib_Member_it_next(&it)) { Member_send_msg(te, msg); } }
inline int io_ensure_sbuf(sbuf *buf, int fd, size_t length) { int rc = 1; size_t ntrans = 0; assert_not(buf, NULL); assert(isvalidsock(fd) && "not a valid socket"); // make sure there's enough for the payload while((size_t)sbuf_data_avail(buf) < length) { // need to read more rc = io_read_sbuf(fd, buf, &ntrans); if(!rc || errno) { if(errno && errno != EBADF) { fail("unexpected error reading from socket"); } errno = 0; break; } check(ntrans != 0, "attempted read returned 0 length"); if(ntrans < length) { dbg("attempted read returned %zu rather than %zu with %jd avail", ntrans, length, (intmax_t)sbuf_data_avail(buf)); } } ensure(return rc); }
Node *Node_parse(bstring buf) { size_t from = 0; assert_not(buf, NULL); return Node_parse_seq(buf, &from); }
void Node_catbstr(bstring str, Node *d, char sep, int follow_sibs) { int rc = 0; assert_not(str, NULL); if(d == NULL) return; if(d->sibling != NULL && follow_sibs) { Node_catbstr(str, d->sibling, sep, follow_sibs); } if(d->type == TYPE_GROUP) { rc = bformata(str, "[%c", sep); assert(rc == BSTR_OK); } if(d->child != NULL) { // we always follow siblings on the children Node_catbstr(str, d->child, sep, 1); } switch(d->type) { case TYPE_BLOB: bformata(str, "'%zu:" , blength(d->value.string)); bconcat(str, d->value.string); bformata(str, "\'%c", sep); break; case TYPE_STRING: bformata(str, "\"%s\"%c" , bdata(d->value.string), sep); break; case TYPE_NUMBER: bformata(str, "%llu%c", d->value.number, sep); break; case TYPE_FLOAT: bformata(str, "%f%c", d->value.floating, sep); break; case TYPE_GROUP: if(!d->name || bchar(d->name, 0) == '@') { rc = bformata(str, "]%c", sep); assert(rc == BSTR_OK); } break; case TYPE_INVALID: // fallthrough default: assert(!"invalid type for node"); break; } if(d->name != NULL) { rc = bformata(str, "%s%c", bdata(d->name), sep); assert(rc == BSTR_OK); } }
int Hub_init(char *argv_0) { assert_not(argv_0, NULL); check(CryptState_init(), "failed to init crypto"); server_init(argv_0); return 1; on_fail(return 0); }
void Hub_connection_handler(void *data) { assert_not(data, NULL); MyriadClient *client = (MyriadClient *)data; Hub *hub = (Hub *)client->server->data; Hub_exec(hub, UEv_OPEN); Hub_queue_conn(hub, client); Hub_exec(hub, UEv_CLOSE); }
int FrameSource_send(FrameSource frame, bstring header, Node *msg, int flush) { int rc = 0; bstring data = Node_bstr(msg, 1); uint16_t msg_len = 0; size_t nout; assert_not(header, NULL); assert_not(msg, NULL); // convert the msg to a bstring to find out the full size check(data, "failed to build bstring from msg Node"); // make sure the sbuf has enough space msg_len = blength(header) + blength(data); if(sbuf_space_avail(frame.out) < msg_len) { rc = io_flush_sbuf(frame.fd, frame.out, &nout); check(rc, "failed to flush sbuf to make room"); check_then(sbuf_space_avail(frame.out) >= msg_len, "insufficient space available in sbuf", rc = 0); } // write the length, then header, then msg rc = sbuf_put_htons(frame.out, msg_len); check(rc, "failed to write length"); rc = sbuf_write_bstr(frame.out, header); check(rc, "failed to write header"); rc = sbuf_write_bstr(frame.out, data); check(rc, "failed to write body"); if(flush) { rc = io_flush_sbuf(frame.fd, frame.out, &nout); check(rc, "failed to write to frame.fd"); } ensure(bdestroy(data); return rc); }
Node *Node_parse_seq(bstring buf, size_t *from) { size_t nread = *from; stackish_parser parser; stackish_parser_init(&parser); char last = bchar(buf, blength(buf) - 1); assert_not(buf, NULL); assert_not(from, NULL); // make sure that the string ends in at least one space of some kind for the parser check(last == ' ' || last == '\n' || last == '\t', "buffer doesn't end in either ' \\n\\t'"); nread = stackish_parser_execute(&parser, (const char *)bdata(buf), blength(buf), nread); check(!stackish_parser_has_error(&parser), "parsing error on stackish string"); while(stackish_more(&parser) && !stackish_parser_is_finished(&parser) && nread < (size_t)blength(buf)) { assert(nread+stackish_more(&parser)+1 < (size_t)blength(buf) && "buffer overflow"); // there is a blob that we have to pull out in order to continue nread = stackish_parser_execute(&parser, (const char *)bdata(buf), blength(buf), nread+stackish_more(&parser)+1); check(!stackish_parser_has_error(&parser), "parsing error after BLOB"); } *from = nread + 1; // skip over a last trailing newline while(bchar(buf, *from) == '\n') (*from)++; return parser.root; on_fail(dbg("failed parsing after %zu bytes", nread); stackish_node_clear(&parser); *from = nread + 1; return NULL); }
bstring Node_bstr(Node *d, int follow_sibs) { int rc = 0; bstring temp = bfromcstr(""); assert_mem(temp); assert_not(d, NULL); Node_catbstr(temp, d, ' ', follow_sibs); rc = bconchar(temp, '\n'); assert(rc == BSTR_OK && "failed to append separator char"); return temp; }
Node *FrameSource_recv(FrameSource frame, bstring *hbuf, Node **header) { Node *msg = NULL; unsigned short length = 0; int rc = 0; size_t from = 0; bstring data = NULL; assert_not(header, NULL); *hbuf = NULL; *header = NULL; rc = io_ensure_sbuf(frame.in, frame.fd, sizeof(uint16_t)); if(!rc) return NULL; // got closed, nothing to do rc = sbuf_get_ntohs(frame.in, &length); check(rc, "length read failure"); check(length > 0, "zero length message"); rc = io_ensure_sbuf(frame.in, frame.fd, length); check(rc, "io read failure"); data = sbuf_read_bstr(frame.in, length); check(data, "failed to read a single bstr"); check(blength(data) == length, "didn't get what we asked for from the sbuf"); *header = Node_parse_seq(data, &from); check(*header, "failed to parse a header"); // carve out the hbuf bstring for comparison *hbuf = bmidstr(data, 0, from); if(from < length) { // more to read msg = Node_parse_seq(data, &from); check(msg, "failed to read body"); } check(from == length, "trailing data violates"); ensure(bdestroy(data); return msg); }
void Node_dump(Node *d, char sep, int follow_sibs) { int i = 0; bstring str = Node_bstr(d, follow_sibs); assert_not(d, NULL); // go through and convert non-printables to printable, but not the last \n for(i = 0; i < blength(str)-1; i++) { if(!isprint(str->data[i])) { str->data[i] = str->data[i] % (126-32) + 32; } } fwrite(str->data, blength(str), 1, stderr); if(bchar(str,blength(str)-1) != '\n') { fprintf(stderr, "\n"); } bdestroy(str); }
int coro_test_4( co_t *co_p ) { if ( *co_p ) goto **co_p; /* begin */ do { assert_not( inside_test_3 ); do { /* yield */ *co_p = &&L__7; return CO_YIELD; L__7:; } while ( 0 ); } while ( inside_test_3 != -1 ); /* end */ *co_p = &&L__END_test_4; L__END_test_4: return CO_END; }
int Node_decons(Node *root, int copy, const char *format, ...) { const char *cur = format; va_list args; va_start (args, format); Node *cur_node = root; assert_not(root, NULL); assert_not(format, NULL); #define UP() { cur_node = cur_node->parent; if(cur_node == NULL) break; } #define NEXT() { if(cur_node->sibling) cur_node = cur_node->sibling; if(cur_node == NULL) break; } for(; *cur != '\0'; cur++) { if(cur_node == NULL) { log(ERROR, "deconstruct ran out at char #%jd (%c) in the spec: %s", (intmax_t)(cur-format), *cur, format); break; } switch(*cur) { case '[': cur_node = cur_node->child; break; case 'n': { uint64_t *number = va_arg(args, uint64_t *); check_type(number, NUMBER, cur_node); *number = cur_node->value.number; NEXT(); break; } case 'f': { double *floating = va_arg(args, double *); *floating = cur_node->value.floating; check_type(floating, FLOAT, cur_node); NEXT(); break; } case 's': { bstring *str = va_arg(args, bstring *); check_type(str, STRING, cur_node); if(copy) *str = bstrcpy(cur_node->value.string); else *str = cur_node->value.string; NEXT(); break; } case 'b': { bstring *blob = va_arg(args, bstring *); check_type(blob, BLOB, cur_node); if(copy) *blob = bstrcpy(cur_node->value.string); else *blob = cur_node->value.string; NEXT(); break; } case ']': { UP(); NEXT(); break; } case '@': { const char *attr = va_arg(args, const char *); check(attr != NULL, "NULL for given for ATTR name"); check_then(cur_node->name && biseqcstr(cur_node->name, attr), "wrong attribute name at:", Node_dump(cur_node, ' ', 1)); // just confirm but don't go to the next one break; } case 'w': { UP(); const char *word = va_arg(args, const char *); check(word != NULL, "NULL given for word"); check_then(cur_node->name && biseqcstr(cur_node->name, word), "wrong word name at:", Node_dump(cur_node, ' ', 1)); NEXT(); break; } case 'G': { Node **group = va_arg(args, Node **); check(group != NULL, "NULL given for group"); check(*group == NULL, "Output var wasn't NULL, must be NULL."); *group = cur_node; NEXT(); break; } case '.': NEXT(); break; default: { fail("invalid char in spec"); break; } } } va_end(args); check(*cur == '\0', "didn't process whole specification"); return 1; on_fail(return 0); }
int coro__ut_data_2( co_t *co_p ) { static dword i; if ( *co_p ) goto **co_p; /* begin */ data_set_word( var__ut_word, 1 ); data_set_dword( var__ut_array_3, 1 ); data_reset_all( peek__ut_data_1 ); data_set_dword( var__ut_array_0, 0x55555555 ); for ( i = 0; i < CYCLE_COUNT; i++ ) { do { /* wait */ *co_p = &&L__5; L__5: if (!( data_get_changed( peek__ut_data_2, var__ut_byte ))) { /* cond */ return CO_WAIT; } } while ( 0 ); /* 2 */ data_reset( peek__ut_data_2, var__ut_byte ); assert_u32_eq(( byte ) i, data_get_byte( var__ut_byte )); data_set_word( var__ut_word, ( word ) i ); do { /* wait */ *co_p = &&L__6; L__6: if (!( data_get_changed( peek__ut_data_2, var__ut_array_1 ))) { /* cond */ return CO_WAIT; } } while ( 0 ); /* 4 */ data_reset( peek__ut_data_2, var__ut_array_1 ); data_set_dword( var__ut_array_3, i << 8 ); assert_u32_eq( data_get_dword( var__ut_array_3 ), data_get_dword( var__ut_array_1 )); data_set_dword( var__ut_array_2, data_get_dword( var__ut_array_0 )); data_set_dword( var__ut_array_0, 0 ); do { /* wait */ *co_p = &&L__7; L__7: if (!( data_get_changed( peek__ut_data_2, var__ut_float ))) { /* cond */ return CO_WAIT; } } while ( 0 ); /* 6 */ data_set_float( var__ut_float, data_get_float( var__ut_float ) + 0.25 ); data_reset( peek__ut_data_2, var__ut_float ); } assert_float_eq(( float )( CYCLE_COUNT >> 1 ), data_get_float( var__ut_float ), 0.0 ); /* Voting operations */ /* I: - II: - III: - M: - */ assert_not( data_get_changed( peek__ut_data_2, var__ut_vote )); assert_not( voted_valid( var__ut_vote )); /* I: - II: 0 III: - M: - */ voted_set_byte( var__ut_vote, 2, 0, &vote_byte ); assert_not( data_get_changed( peek__ut_data_2, var__ut_vote )); assert_not( voted_valid( var__ut_vote )); /* I: - II: 0 III: 0 M: 0 */ voted_set_byte( var__ut_vote, 3, 0, &vote_byte ); assert( data_get_changed( peek__ut_data_2, var__ut_vote )); data_reset( peek__ut_data_2, var__ut_vote ); assert( voted_valid( var__ut_vote )); assert_u32_eq( 0, data_get_byte( var__ut_vote )); /* I: - II: 0 III: 1 M: - */ voted_set_byte( var__ut_vote, 3, 1, &vote_byte ); assert( data_get_changed( peek__ut_data_2, var__ut_vote )); data_reset( peek__ut_data_2, var__ut_vote ); assert_not( voted_valid( var__ut_vote )); do { /* yield */ *co_p = &&L__8; return CO_YIELD; L__8:; } while ( 0 ); /* I: 1 II: 0 III: 1 M: 1 */ voted_set_byte( var__ut_vote, 1, 1, &vote_byte ); assert( data_get_changed( peek__ut_data_2, var__ut_vote )); data_reset( peek__ut_data_2, var__ut_vote ); assert( voted_valid( var__ut_vote )); assert_u32_eq( 1, data_get_byte( var__ut_vote )); /* I: 1 II: 0 III: 0 M: 0 */ voted_set_byte( var__ut_vote, 3, 0, &vote_byte ); assert( data_get_changed( peek__ut_data_2, var__ut_vote )); data_reset( peek__ut_data_2, var__ut_vote ); assert( voted_valid( var__ut_vote )); assert_u32_eq( 0, data_get_byte( var__ut_vote )); /* I: 1 II: 2 III: 0 M: - */ voted_set_byte( var__ut_vote, 2, 2, &vote_byte ); assert( data_get_changed( peek__ut_data_2, var__ut_vote )); data_reset( peek__ut_data_2, var__ut_vote ); assert_not( voted_valid( var__ut_vote )); /* I: 3 II: 2 III: 3 M: 3 */ voted_set_byte( var__ut_vote, 1, 3, &vote_byte ); voted_set_byte( var__ut_vote, 3, 3, &vote_byte ); assert( data_get_changed( peek__ut_data_2, var__ut_vote )); data_reset( peek__ut_data_2, var__ut_vote ); assert( voted_valid( var__ut_vote )); assert_u32_eq( 3, data_get_byte( var__ut_vote )); do { /* yield */ *co_p = &&L__9; return CO_YIELD; L__9:; } while ( 0 ); /* I: 3 II: 3 III: 3 M: 3 */ voted_set_byte( var__ut_vote, 2, 3, &vote_byte ); assert_not( data_get_changed( peek__ut_data_2, var__ut_vote )); assert( voted_valid( var__ut_vote )); assert_u32_eq( 3, data_get_byte( var__ut_vote )); /* I: 4 II: 3 III: 3 M: 3 */ voted_set_byte( var__ut_vote, 1, 4, &vote_byte ); assert_not( data_get_changed( peek__ut_data_2, var__ut_vote )); assert( voted_valid( var__ut_vote )); assert_u32_eq( 3, data_get_byte( var__ut_vote )); /* RESET */ voted_set_byte( var__ut_vote, 3, 2, &vote_byte ); data_reset( peek__ut_data_2, var__ut_vote ); /* end */ *co_p = &&L__END__ut_data_2; L__END__ut_data_2: return CO_END; }
int coro__ut_data_1( co_t *co_p ) { static dword i; if ( *co_p ) goto **co_p; /* begin */ data_clear_watch( peek__ut_data_1 ); data_watch( peek__ut_data_1, _ut_data_1_watch ); data_set_byte( var__ut_byte, 1 ); data_set_dword( var__ut_array_1, 1 ); data_set_float( var__ut_float, 0.0 ); data_reset_all( peek__ut_data_2 ); /* Main operations */ for ( i = 0; i < CYCLE_COUNT; i++ ) { /* 1 */ data_set_byte( var__ut_byte, ( byte ) i ); do { /* wait */ *co_p = &&L__0; L__0: if (!( data_get_changed( peek__ut_data_1, var__ut_word ))) { /* cond */ return CO_WAIT; } } while ( 0 ); /* 3 */ data_reset( peek__ut_data_1, var__ut_word ); assert_u32_eq(( word ) i, data_get_word( var__ut_word )); data_set_dword( var__ut_array_1, i << 8 ); do { /* wait */ *co_p = &&L__1; L__1: if (!( data_get_changed( peek__ut_data_1, var__ut_array_3 ))) { /* cond */ return CO_WAIT; } } while ( 0 ); /* 5 */ data_reset( peek__ut_data_1, var__ut_array_3 ); assert_u32_eq( data_get_dword( var__ut_array_1 ), data_get_dword( var__ut_array_3 )); data_set_dword( var__ut_array_0, data_get_dword( var__ut_array_2 )); data_set_dword( var__ut_array_2, 0 ); data_set_float( var__ut_float, data_get_float( var__ut_float ) + 0.25 ); data_reset( peek__ut_data_1, var__ut_float ); do { /* wait */ *co_p = &&L__2; L__2: if (!( data_get_changed( peek__ut_data_1, var__ut_float ))) { /* cond */ return CO_WAIT; } } while ( 0 ); } assert_u32_eq( 0x55555555, data_get_dword( var__ut_array_0 )); /* Auxiliary operations */ data_set_all_changed( peek__ut_data_1 ); assert(( data_get_changed( peek__ut_data_1, var__ut_word ) && data_get_changed( peek__ut_data_1, var__ut_array_3 ) && data_get_changed( peek__ut_data_1, var__ut_float ) && !data_get_changed( peek__ut_data_1, var__ut_array_1 ) && !data_get_changed( peek__ut_data_1, var__ut_array_2 )) ); data_reset_all( peek__ut_data_1 ); assert_not( data_get_changed_any( peek__ut_data_1 )); data_set_changed( var__ut_byte ); assert_not( data_get_changed_any( peek__ut_data_1 )); data_set_changed( var__ut_float ); assert( data_get_changed_any( peek__ut_data_1 )); do { /* yield */ *co_p = &&L__3; return CO_YIELD; L__3:; } while ( 0 ); data_clear_watch( peek__ut_data_1 ); assert_not( data_get_changed_any( peek__ut_data_1 )); data_watch_array( peek__ut_data_1, _ut_data_array_watch ); data_set_changed( var__ut_float ); data_set_changed( var__ut_word ); data_set_changed( var__ut_array_0 ); assert_not( data_get_changed_any( peek__ut_data_1 )); data_set_changed( var__ut_array_1 ); assert( data_get_changed( peek__ut_data_1, var__ut_array_1 )); data_set_changed( var__ut_array_2 ); assert( data_get_changed( peek__ut_data_1, var__ut_array_2 )); data_set_changed( var__ut_array_3 ); assert( data_get_changed( peek__ut_data_1, var__ut_array_3 )); data_set_changed( var__ut_byte ); assert( data_get_changed( peek__ut_data_1, var__ut_byte )); do { /* yield */ *co_p = &&L__4; return CO_YIELD; L__4:; } while ( 0 ); assert_u32_eq( var__ut_array, data_atovar( data_vartoa( var__ut_array_0 ))); assert_str_eq( "_ut_byte", data_vartoa( data_atovar( "_ut_byte" ))); i = 0x00ABCDEF; data_set( var__ut_array_3, &i ); assert_str_eq( "0x00ABCDEF", data_get_string( __str, var__ut_array_3 )); data_set_string( var__ut_float, "8080.02" ); assert_str_eq( "8080.02", data_get_string( __str, var__ut_float )); assert_str_eq( "word", data_get_type( var__ut_word )); /* end */ *co_p = &&L__END__ut_data_1; L__END__ut_data_1: return CO_END; }
Node *Node_cons(const char *format, ...) { const char *cur = format; va_list args; va_start (args, format); Node *root = NULL; Node *cur_node = NULL; assert_not(format, NULL); #define UP() { cur_node = cur_node->parent; if(cur_node == NULL) break; } for(; *cur != '\0'; cur++) { switch(*cur) { case '[': cur_node = Node_new_group(cur_node); if(root == NULL) { root = cur_node; } break; case 'n': { uint64_t number = va_arg(args, uint64_t); Node *n = Node_new_number(cur_node, number); assert_not(n,NULL); break; } case 'f': { double floating = va_arg(args, double); Node *n = Node_new_float(cur_node, floating); assert_not(n,NULL); break; } case 'b': { bstring blob = va_arg(args, bstring); check(blob != NULL, "NULL given for blob"); Node *n = Node_new_blob(cur_node, blob); assert_not(n,NULL); break; } case 's': { bstring string = va_arg(args, bstring); check(string != NULL, "NULL given for string"); Node *n = Node_new_string(cur_node, string); check(n != NULL, "Failed to create new string node"); break; } case ']': { UP(); break; } case '@': { const char *attr = va_arg(args, const char *); check(attr != NULL, "NULL given for attr"); Node_name(cur_node->child, bfromcstr(attr)); break; } case 'w': { const char *word = va_arg(args, const char *); check(word != NULL, "NULL given for word name"); Node_name(cur_node, bfromcstr(word)); UP(); break; } case 'G': { Node *group = va_arg(args, Node *); check(group != NULL, "NULL given for group to add"); LIST_ADD(Node, cur_node->child, group, sibling); break; } case ' ': case '\t': case '\n': { break; } default: { fail("invalid character in spec"); break; } } } assert(*cur == '\0'); assert(cur_node == NULL); va_end(args); return root; on_fail(return NULL); }