void ring_stabilise_all() { Node *current = NULL; Ring *ring = ring_get(); int i = 0; int done_first = 0; /* current = ring->first_node; while (current != NULL) { i++; */ for (i = 0; i < ring->size; i++) { current = ring->nodes[i]; node_stabilise(current); node_fix_fingers(current); /* current = current->successor != current ? current->successor : NULL; if (done_first && current == ring->first_node) { current = NULL; } if (!done_first) { done_first = 1; } */ } }
int ring_size() { Node *current = NULL; Ring *ring = ring_get(); /* int size = 0; int done_first = 0; current = ring->first_node; while (current != NULL) { size++; current = current->successor != current ? current->successor : NULL; if (done_first && current == ring->first_node) { current = NULL; } if (!done_first) { done_first = 1; } } */ return ring->size; }
int db_worker_run(void *arg) { int running = 1; while (running) { RingEntry e; mtx_lock(&mtx); while (!ring_get(&ring, &e)) { cnd_wait(&cnd, &mtx); } mtx_unlock(&mtx); switch (e.type) { case BLOCK: _db_insert_block(e.p, e.q, e.x, e.y, e.z, e.w); break; case KEY: _db_set_key(e.p, e.q, e.key); break; case COMMIT: _db_commit(); break; case EXIT: running = 0; break; } } return 0; }
/* wait for an event */ int waitevent() { while(1) { /* ring button pressed? */ if(ring_get()) { waitticks(DEBOUNCE); if(ring_get()) { waitticks(DEBOUNCE); if(ring_get()) { while(ring_get()); return EVENT_RING; } } } /* sequence timeout or pending strobe activation? */ if(firstpress) { tick_t time = gettick(); if((time - firstpress) >= TIMEOUT) { return EVENT_TIMEOUT; } if((time - lastpress) >= STROBEDELAY) { return EVENT_STROBE; } } /* command input? */ char input; if(urx(&input)) { switch(input) { case 'O': return EVENT_CMD_OPEN; case 'L': return EVENT_CMD_LOCK; case 'U': return EVENT_CMD_UNLOCK; case 'S': return EVENT_CMD_STROBO_ENABLE; case 's': return EVENT_CMD_STROBO_DISABLE; } } } }
void ring_grow(Ring *ring) { Ring new_ring; RingEntry entry; ring_alloc(&new_ring, ring->capacity * 2); while (ring_get(ring, &entry)) { ring_put(&new_ring, &entry); } free(ring->data); ring->capacity = new_ring.capacity; ring->start = new_ring.start; ring->end = new_ring.end; ring->data = new_ring.data; }
void ring_insert_before(Node *before_node, Node *node) { Ring *ring = ring_get(); node->predecessor = before_node->predecessor; node->successor = before_node; if (before_node->predecessor == NULL) { ring->first_node = node; } else { before_node->predecessor->successor = node; } before_node->predecessor = node; }
void ring_insert_after(Node *after_node, Node *node) { Ring *ring = ring_get(); node->predecessor = after_node; node->successor = after_node->successor; if (after_node->successor == NULL) { ring->last_node = node; } else { after_node->successor->predecessor = node; } after_node->successor = node; }
void ring_print_all() { Node *current = NULL; Ring *ring = ring_get(); int i = 0; printf("%-4s %-11s %-5s %-5s %-7s\n", "Key", "ID", "Pred", "Succ", "# Docs"); printf("---- ----------- ----- ----- -------\n"); for (i = 0; i < ring->size; i++) { current = ring->nodes[i]; node_print(current); } }
void ring_insert(Node *node) { Node *current = NULL; Ring *ring = ring_get(); if (ring->first_node == NULL) { ring->first_node = node; ring->last_node = node; node->predecessor = NULL; node->successor = NULL; } else { current = ring->first_node; /* insert the node into the doubly linked list * while maintaining sort order. First get the * node we will insert after. */ while (current != NULL) { /* if there's no successor we're at the end, so add it here */ if (current->successor == NULL) { if (node->key > current->key) { ring_insert_after(current, node); } else { ring_insert_before(current, node); } break; } else { /* if the successor node is less than the current, insert here */ if ((node->key < current->successor->key) && (node->key > current->key)) { /* insert the node into the Ring */ ring_insert_after(current, node); break; } /* if the node is less and current and greater than predecessor, insert here */ else if ((node->key < current->key) && ((current->predecessor == NULL) || (node->key > current->predecessor->key))) { /* insert the node into the Ring */ ring_insert_before(current, node); break; } } /* go to the successor node in the ring */ current = current->successor != current ? current->successor : NULL; } } }
int8_t GSwifi::parseRequestLine (char *token, uint8_t token_size) { uint8_t i; for ( i = 0; i <= token_size; i++ ) { if (ring_isempty( _buf_cmd )) { return -1; // space didn't appear } ring_get( _buf_cmd, token+i, 1 ); if (token[i] == ' ') { token[i] = '\0'; break; } } if ( i == token_size + 1 ) { return -1; // couldnt detect token } return 0; }
int16_t ring_get_all(buffer_data_t *dest, buffer_index_t dest_size, volatile buffer_data_t *buffer, buffer_index_t buffer_size, volatile buffer_index_t *head, volatile buffer_index_t *tail) { buffer_index_t count = 0; int16_t ret_val; buffer_data_t temp_value; do { ret_val = ring_get(&temp_value, buffer, buffer_size, head, tail); if (ERR_NONE != ret_val) break; dest[count++] = temp_value; } while ((count < dest_size)); return count; }
int8_t GSwifi::parseHead2(uint8_t dat, int8_t cid) { if (dat == '\n') { continuous_newlines_ ++; } else if (dat == '\r') { // preserve } else { continuous_newlines_ = 0; if ( ! ring_isfull(_buf_cmd) ) { // ignore if overflowed ring_put( _buf_cmd, dat ); } } if (continuous_newlines_ == 1) { // check "Content-Length: x" header // if it's non 0, wait for more body data // otherwise disconnect after handling response // GS splits HTTP requests/responses into multiple bulk messages, // 1st ends just after headers, and 2nd contains only response body // "Content-Length: " .length = 16 // "Content-Length: 9999".length = 20 // "X-Requested-With: " .length = 18 char content_length_chars[21]; memset( content_length_chars, 0, 21 ); uint8_t copied = ring_get( _buf_cmd, content_length_chars, 20 ); if ((copied >= 16) && (strncmp(content_length_chars, "Content-Length: ", 16) == 0)) { content_length_chars[20] = 0; content_lengths_[ cid ] = atoi(&content_length_chars[16]); } if ((copied >= 18) && (strncmp(content_length_chars, "X-Requested-With: ", 18) == 0)) { has_requested_with_ = true; } ring_clear(_buf_cmd); } if (continuous_newlines_ == 2) { // if detected double (\r)\n, switch to body mode ring_clear(_buf_cmd); return 0; } return -1; }
int HardwareSerialX::read(void) { // if the head isn't ahead of the tail, we don't have any characters if (ring_isempty( _rx_buffer )) { return -1; } else { char c; ring_get( _rx_buffer, &c, 1 ); if (is_limiting && ring_used(_rx_buffer) < XONOFF_HYSTERESIS) { send_xon = true; is_limiting = false; sbi(UCSR1B, UDRIE1); } return c; } }
void ring_print(int index, int with_fingers) { Node *current = NULL; Ring *ring = ring_get(); int i = 0; int done_first = 0; current = ring->first_node; if (index) { printf("%-4s %-4s %-11s %-5s %-5s %-7s\n", "Idx", "Key", "ID", "Pred", "Succ", "# Docs"); printf("---- ---- ----------- ----- ----- -------\n"); } if (!index) { printf("%-4s %-11s %-5s %-5s %-7s\n", "Key", "ID", "Pred", "Succ", "# Docs"); printf("---- ----------- ----- ----- -------\n"); } while (current != NULL) { i++; if (index) { printf("%-4d ", i); } node_print(current); if (with_fingers) { node_print_finger_table(current); } current = current->successor != current ? current->successor : NULL; if (done_first && current == ring->first_node) { current = NULL; } if (!done_first) { done_first = 1; } } }
char GSwifi::bufferGet() { char letter; ring_get(_buf_cmd, &letter, 1); return letter; }
int main() { ok( 1, "ok" ); { struct RingBuffer buf_; struct RingBuffer *buf = &buf_; char data[65]; ring_init( buf, data, 65 ); ok( ring_used(buf) == 0, "0 used" ); ok( ring_isempty(buf) == 1, "is empty" ); ring_put(buf, 'a'); ok( ring_used(buf) == 1, "1 used after put" ); ok( ring_isfull(buf) == 0, "not full" ); ok( ring_isempty(buf) == 0, "is empty" ); char buf2[64]; ring_get(buf, &buf2[0], 1); ok( buf2[0] == 'a', "get" ); ok( ring_used(buf) == 0, "0 used after get" ); ok( ring_isfull(buf) == 0, "not full" ); ok( ring_isempty(buf) == 1, "is empty" ); ring_put(buf, 'b'); ring_clear(buf); ok( ring_used(buf) == 0, "0 used after clear" ); ok( ring_isfull(buf) == 0, "not full" ); ok( ring_isempty(buf) == 1, "is empty" ); ring_put(buf, '0'); ring_put(buf, '1'); ring_put(buf, '2'); ring_put(buf, '3'); ring_put(buf, '4'); ring_put(buf, '5'); ring_put(buf, '6'); ring_put(buf, '7'); ring_put(buf, '8'); ring_put(buf, '9'); ring_put(buf, 'a'); ring_put(buf, 'b'); ring_put(buf, 'c'); ring_put(buf, 'd'); ring_put(buf, 'e'); ring_put(buf, 'f'); ring_put(buf, '0'); ring_put(buf, '1'); ring_put(buf, '2'); ring_put(buf, '3'); ring_put(buf, '4'); ring_put(buf, '5'); ring_put(buf, '6'); ring_put(buf, '7'); ring_put(buf, '8'); ring_put(buf, '9'); ring_put(buf, 'a'); ring_put(buf, 'b'); ring_put(buf, 'c'); ring_put(buf, 'd'); ring_put(buf, 'e'); ring_put(buf, 'f'); ring_put(buf, '0'); ring_put(buf, '1'); ring_put(buf, '2'); ring_put(buf, '3'); ring_put(buf, '4'); ring_put(buf, '5'); ring_put(buf, '6'); ring_put(buf, '7'); ring_put(buf, '8'); ring_put(buf, '9'); ring_put(buf, 'a'); ring_put(buf, 'b'); ring_put(buf, 'c'); ring_put(buf, 'd'); ring_put(buf, 'e'); ring_put(buf, 'f'); ring_put(buf, '0'); ring_put(buf, '1'); ring_put(buf, '2'); ring_put(buf, '3'); ring_put(buf, '4'); ring_put(buf, '5'); ring_put(buf, '6'); ring_put(buf, '7'); ring_put(buf, '8'); ring_put(buf, '9'); ring_put(buf, 'a'); ring_put(buf, 'b'); ring_put(buf, 'c'); ring_put(buf, 'd'); ring_put(buf, 'e'); ring_put(buf, 'f'); ok( ring_used(buf) == 64, "64 used after 64 puts" ); ok( ring_isfull(buf) == 1, "is full" ); ok( ring_isempty(buf) == 0, "is empty" ); // dropped feature to protect buffer from overflow // ok( ring_put(buf, 'x') == -1, "can't put into full" ); uint8_t fetched = ring_get(buf, &buf2[0], 64); ok( buf2[0] == '0', "get 1" ); ok( buf2[1] == '1', "get 2" ); ok( buf2[2] == '2', "get 3" ); ok( buf2[3] == '3', "get 4" ); ok( fetched == 64, "fetched all" ); ok( ring_used(buf) == 0, "0 used after all get" ); ok( ring_isfull(buf) == 0, "not full again" ); ok( ring_isempty(buf) == 1, "is empty" ); } done_testing(); }
void GSwifi::parseLine () { static char buf[GS_CMD_SIZE]; while (! ring_isempty(_buf_cmd)) { // received "\n" uint8_t i = 0; while ( (! ring_isempty(_buf_cmd)) && (i < sizeof(buf) - 1) ) { ring_get( _buf_cmd, &buf[i], 1 ); if (buf[i] == '\n') { break; } i ++; } if (i == 0) continue; buf[i] = 0; if ( (gs_mode_ == GSMODE_COMMAND) && (gs_commandmode_ != GSCOMMANDMODE_NONE) ) { parseCmdResponse(buf); } if (strncmp(buf, P("CONNECT "), 8) == 0 && buf[8] >= '0' && buf[8] <= 'F' && buf[9] != 0) { // connect from client // CONNECT 0 1 192.168.2.1 63632 // 1st cid is our http server's // 2nd cid is for client // next line will be "[ESC]Z10140GET / ..." int8_t cid = x2i(buf[10]); // 2nd cid = HTTP client cid ASSERT((0 <= cid) && (cid <= 16)); setCidIsRequest(cid, true); content_lengths_[ cid ] = 0; // don't close other connections, // other connections close theirselves on their turn // ignore client's IP and port } else if (strncmp(buf, P("DISCONNECT "), 11) == 0) { int8_t cid = x2i(buf[11]); ASSERT((0 <= cid) && (cid <= 16)); if (cid == server_cid_) { // if it's our server, this is fatal reset(); } else if (! cidIsRequest(cid) ) { // request *from* us was disconnected (ex: polling) dispatchResponseHandler(cid, HTTP_STATUSCODE_DISCONNECT, GSREQUESTSTATE_ERROR); } } else if (strncmp(buf, P("DISASSOCIATED"), 13) == 0 || strncmp(buf, P("Disassociat"), 11) == 0) { // Disassociated // Disassociation Event clear(); on_disconnect_(); gs_failure_ = true; } else if (strncmp(buf, P("APP Reset"), 9) == 0 || strncmp(buf, P("Serial2WiFi APP"), 15) == 0) { // APP Reset-APP SW Reset // APP Reset-Wlan Except // Serial2Wifi APP on_reset_(); gs_failure_ = true; } // else if (strncmp(buf, P("Out of StandBy-Timer"), 20) == 0 || // strncmp(buf, P("Out of StandBy-Alarm"), 20) == 0) { // } // else if (strncmp(buf, P("Out of Deep Sleep"), 17) == 0 ) { // } } }
// received a character from UART void GSwifi::parseByte(uint8_t dat) { static uint8_t next_token; // split each byte into tokens (cid,ip,port,length,data) static bool escape = false; char temp[GS_MAX_PATH_LENGTH+1]; if (dat == ESCAPE) { // 0x1B : Escape GSLOG_PRINT("e< "); } else { // if (next_token != NEXT_TOKEN_DATA) { GSLOG_WRITE(dat); } if (gs_mode_ == GSMODE_COMMAND) { if (escape) { // esc switch (dat) { case 'O': case 'F': // ignore break; case 'Z': case 'H': gs_mode_ = GSMODE_DATA_RX_BULK; next_token = NEXT_TOKEN_CID; break; default: // GSLOG_PRINT("!E1 "); GSLOG_PRINTLN2(dat,HEX); break; } escape = false; } else { if (dat == ESCAPE) { escape = true; } else if (dat == '\n') { // end of line parseLine(); } else if (dat != '\r') { if ( ! ring_isfull(_buf_cmd) ) { ring_put(_buf_cmd, dat); } else { GSLOG_PRINTLN("!E2"); } } } return; } else if (gs_mode_ != GSMODE_DATA_RX_BULK) { return; } static uint16_t len; static char len_chars[5]; static int8_t current_cid; static GSREQUESTSTATE request_state; if (next_token == NEXT_TOKEN_CID) { // dat is cid current_cid = x2i(dat); ASSERT((0 <= current_cid) && (current_cid <= 16)); next_token = NEXT_TOKEN_LENGTH; len = 0; } else if (next_token == NEXT_TOKEN_LENGTH) { // Data Length is 4 ascii char represents decimal value i.e. 1400 byte (0x31 0x34 0x30 0x30) len_chars[ len ++ ] = dat; if (len >= 4) { len_chars[ len ] = 0; len = atoi(len_chars); // length of data next_token = NEXT_TOKEN_DATA; if (content_lengths_[ current_cid ] > 0) { // this is our 2nd bulk message from GS for this response // we already swallowed HTTP response headers, // following should be body request_state = GSREQUESTSTATE_BODY; } else { request_state = GSREQUESTSTATE_HEAD1; } ring_clear( _buf_cmd ); // reuse _buf_cmd to store HTTP request } } else if (next_token == NEXT_TOKEN_DATA) { len --; if (cidIsRequest(current_cid)) { // request against us static uint16_t error_code; static int8_t routeid; switch (request_state) { case GSREQUESTSTATE_HEAD1: if (dat != '\n') { if ( ! ring_isfull(_buf_cmd) ) { ring_put( _buf_cmd, dat ); } // ignore overflowed } else { // end of request line // reuse "temp" buffer to parse method and path int8_t result = parseRequestLine((char*)temp, 7); GSMETHOD method = GSMETHOD_UNKNOWN; if ( result == 0 ) { method = x2method(temp); result = parseRequestLine((char*)temp, GS_MAX_PATH_LENGTH); } if ( result != 0 ) { // couldn't detect method or path request_state = GSREQUESTSTATE_ERROR; error_code = 400; ring_clear(_buf_cmd); break; } routeid = router(method, temp); if ( routeid < 0 ) { request_state = GSREQUESTSTATE_ERROR; error_code = 404; ring_clear(_buf_cmd); break; } request_state = GSREQUESTSTATE_HEAD2; continuous_newlines_ = 0; content_lengths_[ current_cid ] = 0; has_requested_with_ = false; ring_clear(_buf_cmd); } break; case GSREQUESTSTATE_HEAD2: if(0 == parseHead2(dat, current_cid)) { request_state = GSREQUESTSTATE_BODY; // dispatched once, at start of body dispatchRequestHandler(current_cid, routeid, GSREQUESTSTATE_BODY_START); } break; case GSREQUESTSTATE_BODY: if (content_lengths_[ current_cid ] > 0) { content_lengths_[ current_cid ] --; } if (ring_isfull(_buf_cmd)) { dispatchRequestHandler(current_cid, routeid, request_state); // POST, user callback should write() } ring_put(_buf_cmd, dat); break; case GSREQUESTSTATE_ERROR: // skip until received whole request break; case GSREQUESTSTATE_RECEIVED: default: break; } // end of bulk transfered data if (len == 0) { gs_mode_ = GSMODE_COMMAND; if ( request_state == GSREQUESTSTATE_ERROR ) { writeHead( current_cid, error_code ); writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, current_cid ); } else { if (content_lengths_[ current_cid ] == 0) { // if Content-Length header was longer than <ESC>Z length, // we wait til next bulk transfer request_state = GSREQUESTSTATE_RECEIVED; } // user callback should write(), writeEnd() and close() dispatchRequestHandler(current_cid, routeid, request_state); } ring_clear(_buf_cmd); } } else { // is request from us static uint16_t status_code; switch (request_state) { case GSREQUESTSTATE_HEAD1: if (dat != '\n') { if ( ! ring_isfull(_buf_cmd) ) { // ignore if overflowed ring_put( _buf_cmd, dat ); } } else { uint8_t i=0; // skip 9 characters "HTTP/1.1 " while (i++ < 9) { ring_get( _buf_cmd, &temp[0], 1 ); } // copy 3 numbers representing status code into temp buffer temp[ 3 ] = 0; int8_t count = ring_get( _buf_cmd, temp, 3 ); if (count != 3) { // protocol error // we should receive something like: "200 OK", "401 Unauthorized" status_code = 999; request_state = GSREQUESTSTATE_ERROR; break; } status_code = atoi(temp); request_state = GSREQUESTSTATE_HEAD2; continuous_newlines_ = 0; content_lengths_[ current_cid ] = 0; ring_clear(_buf_cmd); } break; case GSREQUESTSTATE_HEAD2: if(0 == parseHead2(dat, current_cid)) { request_state = GSREQUESTSTATE_BODY; // dispatched once, at start of body dispatchResponseHandler(current_cid, status_code, GSREQUESTSTATE_BODY_START); } break; case GSREQUESTSTATE_BODY: if (content_lengths_[ current_cid ] > 0) { content_lengths_[ current_cid ] --; } if (ring_isfull(_buf_cmd)) { dispatchResponseHandler(current_cid, status_code, GSREQUESTSTATE_BODY); } ring_put(_buf_cmd, dat); break; case GSREQUESTSTATE_ERROR: case GSREQUESTSTATE_RECEIVED: default: break; } if (len == 0) { gs_mode_ = GSMODE_COMMAND; if ( request_state == GSREQUESTSTATE_ERROR ) { dispatchResponseHandler(current_cid, status_code, request_state); } else { if (content_lengths_[ current_cid ] == 0) { // if Content-Length header was longer than <ESC>Z length, // we wait til all response body received. // we need to close our clientRequest before handling it. // GS often locks when closing 2 connections in a row // ex: POST /keys from iPhone (cid:1) -> POST /keys to server (cid:2) // response from server arrives -> close(1) -> close(2) -> lock!! // the other way around: close(2) -> close(1) doesn't lock :( request_state = GSREQUESTSTATE_RECEIVED; } dispatchResponseHandler(current_cid, status_code, request_state); } ring_clear( _buf_cmd ); } } // is response } // (next_token == NEXT_TOKEN_DATA) }