void env_universal_barrier() { ASSERT_IS_MAIN_THREAD(); message_t *msg; fd_set fds; if (!s_env_univeral_inited || is_dead()) return; barrier_reply = 0; /* Create barrier request */ msg= create_message(BARRIER, 0, 0); msg->count=1; env_universal_server.unsent.push(msg); /* Wait until barrier request has been sent */ debug(3, L"Create barrier"); while (1) { try_send_all(&env_universal_server); check_connection(); if (env_universal_server.unsent.empty()) break; if (env_universal_server.fd == -1) { reconnect(); debug(2, L"barrier interrupted, exiting"); return; } FD_ZERO(&fds); FD_SET(env_universal_server.fd, &fds); select(env_universal_server.fd+1, 0, &fds, 0, 0); } /* Wait for barrier reply */ debug(3, L"Sent barrier request"); while (!barrier_reply) { if (env_universal_server.fd == -1) { reconnect(); debug(2, L"barrier interrupted, exiting (2)"); return; } FD_ZERO(&fds); FD_SET(env_universal_server.fd, &fds); select(env_universal_server.fd+1, &fds, 0, 0, 0); env_universal_read_all(); } debug(3, L"End barrier"); }
static int give_write_copy (int requester_id, int request_id, int page_number) { int result; printf("%d: pre-lock\n", thisid); pthread_mutex_lock(&locks[page_number]); printf("%d: post-lock\n", thisid); int owner_id = get_owner(page_number); if (owner_id != thisid) { printf("%d: wtf\n", thisid); pthread_mutex_unlock(&locks[page_number]); return -E_INCORRECT_OWNER; } struct PageStatus *page_status = get_page_status(page_number); printf("%d: page_status->status: %d\n", thisid, page_status->status); switch (page_status->status) { case READABLE: { int i; int had_read_only; for (i = 0; i < nowners; i++) { if (i == requester_id) { had_read_only = (page_status->status_by_owner[i] == READING); continue; } if (i == thisid) { if (page_status->status_by_owner[i] == READING) { // Set local page to PROT_NONE at end of function continue; } else { // This shouldn't happen - the local copy should become // readable as soon the page status becomes READABLE result = -E_INCONSISTENT_STATE; break; } } if (page_status->status_by_owner[i] == READING) { // Tell i that it is INVALIDATED printf("%d: Telling %d that it is INVALIDATED\n", thisid, i); struct Message m = create_message(SET_PERMISSION, INVALIDATED, page_number); printf("%d: sending message of type %c\n", thisid, m.msg_type); result = send_to(i, &m); if (result < 0) break; page_status->status_by_owner[i] = INVALIDATED; } } page_status->status_by_owner[requester_id] = MODIFYING; page_status->modifying_owner = requester_id; page_status->status = MODIFIED; if (requester_id == thisid) { // Set local page to PROT_READ_WRITE printf("%d: Setting local page %d to PROT_READ_WRITE\n", thisid, page_number); result = set_permissions((void *) get_pageaddr(page_number), PGSIZE, PROT_READ_WRITE); if (result < 0) break; } else { if (had_read_only) { // Tell requester_id that it has PROT_READ_WRITE access struct Message m = create_message(SET_PERMISSION, MODIFYING, page_number); m.is_response = 1; if (request_id == NO_RESPONSE) { result = E_INCONSISTENT_STATE; break; } m.index = request_id; result = send_to(requester_id, &m); if (result < 0) break; } else { // Transfer page over network to requester_id and tell it // it has PROT_READ_WRITE access struct Message m = create_message(SEND_PAGE, MODIFYING, page_number); memcpy((void *) m.page, (void *) get_pageaddr(page_number), PGSIZE); m.is_response = 1; if (request_id == NO_RESPONSE) { result = E_INCONSISTENT_STATE; break; } m.index = request_id; result = send_to(requester_id, &m); if (result < 0) break; } } // Set local page to PROT_NONE result = set_permissions((void *) get_pageaddr(page_number), PGSIZE, PROT_NONE); if (result < 0) break; page_status->status_by_owner[thisid] = INVALIDATED; result = 0; break; } case MODIFIED: { int modifier = page_status->modifying_owner; if (modifier == requester_id) { // The modifier should have read-write permissions, in which // case a page not fault should not be thrown and this // should never be called. result = -E_INCONSISTENT_STATE; break; } if (modifier == thisid) { // Set local page to PROT_NONE at end of method } else { // Tell modifier that it is INVALIDATED // Get modified page from modifier struct Message m = create_message(REQUEST_PAGE, INVALIDATED, page_number); // Upon receiving the message we should map the page locally result = send_and_wait_for_response(modifier, &m); if (result < 0) break; // Local page should already be set PROT_READ } page_status->status_by_owner[modifier] = INVALIDATED; page_status->status_by_owner[requester_id] = MODIFYING; page_status->modifying_owner = requester_id; if (requester_id == thisid) { // Set local page to PROT_READ_WRITE result = set_permissions((void *) get_pageaddr(page_number), PGSIZE, PROT_READ_WRITE); if (result < 0) break; } else { // Transfer page over network to requester_id and tell it it has // PROT_READ_WRITE access struct Message m = create_message(SEND_PAGE, MODIFYING, page_number); memcpy((void *) m.page, (void *) get_pageaddr(page_number), PGSIZE); m.is_response = 1; if (request_id == NO_RESPONSE) { result = E_INCONSISTENT_STATE; break; } m.index = request_id; result = send_to(requester_id, &m); if (result < 0) break; // Set local page to PROT_NONE result = set_permissions((void *) get_pageaddr(page_number), PGSIZE, PROT_NONE); if (result < 0) break; } result = 0; break; } default: { printf("Unhandled page status in give_write_copy.\n"); exit(-E_UNHANDLED_PAGE_STATUS); } } pthread_mutex_unlock(&locks[page_number]); return result; }
int receive_message (int sender_id, struct Message *m) { printf("%d: received message from %d of type %c\n", thisid, sender_id, m->msg_type); int result; switch (m->msg_type) { case (REQUEST_PAGE): { pthread_mutex_lock(&locks[m->page_number]); void *pageaddr = (void *) get_pageaddr(m->page_number); result = set_permissions(pageaddr, PGSIZE, m->permissions); if (result < 0) break; struct Message response = create_message(SEND_PAGE, READING, m->page_number); if (m->index == NO_RESPONSE) { result = E_INCONSISTENT_STATE; break; } response.index = m->index; response.is_response = 1; memcpy((void *) response.page, pageaddr, PGSIZE); result = send_to(sender_id, &response); pthread_mutex_lock(&locks[m->page_number]); break; } case (SEND_PAGE): { pthread_mutex_lock(&locks[m->page_number]); void *pageaddr = (void *) get_pageaddr(m->page_number); result = set_permissions(pageaddr, PGSIZE, PROT_READ_WRITE); if (result < 0) break; memcpy(pageaddr, (void *) m->page, PGSIZE); result = set_permissions(pageaddr, PGSIZE, m->permissions); if (m->is_response) { pthread_cond_signal(&waits[m->index]); } pthread_mutex_unlock(&locks[m->page_number]); break; } case (SET_PERMISSION): { pthread_mutex_lock(&locks[m->page_number]); void *pageaddr = (void *) get_pageaddr(m->page_number); result = set_permissions(pageaddr, PGSIZE, m->permissions); if (m->is_response) { pthread_cond_signal(&waits[m->index]); } pthread_mutex_unlock(&locks[m->page_number]); break; } case (REQUEST_PERMISSION): { if (m->permissions = READING) { give_read_copy(sender_id, m->index, m->page_number); } else if (m->permissions = MODIFYING) { give_write_copy(sender_id, m->index, m->page_number); } else { result = -E_UNHANDLED_PAGE_STATUS; break; } break; } default: { printf("Unhandled message type in give_read_copy: %c\n", m->msg_type); exit(-E_UNHANDLED_MESSAGE_TYPE); } } return result; }
static void start_element(void *data, const char *element_name, const char **atts) { struct parse_context *ctx = data; struct interface *interface; struct message *message; struct arg *arg; struct enumeration *enumeration; struct entry *entry; struct description *description = NULL; const char *name = NULL; const char *type = NULL; const char *interface_name = NULL; const char *value = NULL; const char *summary = NULL; const char *since = NULL; const char *allow_null = NULL; const char *enumeration_name = NULL; const char *bitfield = NULL; int i, version = 0; ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); for (i = 0; atts[i]; i += 2) { if (strcmp(atts[i], "name") == 0) name = atts[i + 1]; if (strcmp(atts[i], "version") == 0) { version = strtouint(atts[i + 1]); if (version == -1) fail(&ctx->loc, "wrong version (%s)", atts[i + 1]); } if (strcmp(atts[i], "type") == 0) type = atts[i + 1]; if (strcmp(atts[i], "value") == 0) value = atts[i + 1]; if (strcmp(atts[i], "interface") == 0) interface_name = atts[i + 1]; if (strcmp(atts[i], "summary") == 0) summary = atts[i + 1]; if (strcmp(atts[i], "since") == 0) since = atts[i + 1]; if (strcmp(atts[i], "allow-null") == 0) allow_null = atts[i + 1]; if (strcmp(atts[i], "enum") == 0) enumeration_name = atts[i + 1]; if (strcmp(atts[i], "bitfield") == 0) bitfield = atts[i + 1]; } ctx->character_data_length = 0; if (strcmp(element_name, "protocol") == 0) { if (name == NULL) fail(&ctx->loc, "no protocol name given"); ctx->protocol->name = xstrdup(name); ctx->protocol->uppercase_name = uppercase_dup(name); } else if (strcmp(element_name, "copyright") == 0) { } else if (strcmp(element_name, "interface") == 0) { if (name == NULL) fail(&ctx->loc, "no interface name given"); if (version == 0) fail(&ctx->loc, "no interface version given"); interface = create_interface(ctx->loc, name, version); ctx->interface = interface; wl_list_insert(ctx->protocol->interface_list.prev, &interface->link); } else if (strcmp(element_name, "request") == 0 || strcmp(element_name, "event") == 0) { if (name == NULL) fail(&ctx->loc, "no request name given"); message = create_message(ctx->loc, name); if (strcmp(element_name, "request") == 0) wl_list_insert(ctx->interface->request_list.prev, &message->link); else wl_list_insert(ctx->interface->event_list.prev, &message->link); if (type != NULL && strcmp(type, "destructor") == 0) message->destructor = 1; version = version_from_since(ctx, since); if (version < ctx->interface->since) warn(&ctx->loc, "since version not increasing\n"); ctx->interface->since = version; message->since = version; if (strcmp(name, "destroy") == 0 && !message->destructor) fail(&ctx->loc, "destroy request should be destructor type"); ctx->message = message; } else if (strcmp(element_name, "arg") == 0) { if (name == NULL) fail(&ctx->loc, "no argument name given"); arg = create_arg(name); if (!set_arg_type(arg, type)) fail(&ctx->loc, "unknown type (%s)", type); switch (arg->type) { case NEW_ID: ctx->message->new_id_count++; /* fallthrough */ case OBJECT: if (interface_name) arg->interface_name = xstrdup(interface_name); break; default: if (interface_name != NULL) fail(&ctx->loc, "interface attribute not allowed for type %s", type); break; } if (allow_null) { if (strcmp(allow_null, "true") == 0) arg->nullable = 1; else if (strcmp(allow_null, "false") != 0) fail(&ctx->loc, "invalid value for allow-null attribute (%s)", allow_null); if (!is_nullable_type(arg)) fail(&ctx->loc, "allow-null is only valid for objects, strings, and arrays"); } if (enumeration_name == NULL || strcmp(enumeration_name, "") == 0) arg->enumeration_name = NULL; else arg->enumeration_name = xstrdup(enumeration_name); if (summary) arg->summary = xstrdup(summary); wl_list_insert(ctx->message->arg_list.prev, &arg->link); ctx->message->arg_count++; } else if (strcmp(element_name, "enum") == 0) { if (name == NULL) fail(&ctx->loc, "no enum name given"); enumeration = create_enumeration(name); if (bitfield == NULL || strcmp(bitfield, "false") == 0) enumeration->bitfield = false; else if (strcmp(bitfield, "true") == 0) enumeration->bitfield = true; else fail(&ctx->loc, "invalid value (%s) for bitfield attribute (only true/false are accepted)", bitfield); wl_list_insert(ctx->interface->enumeration_list.prev, &enumeration->link); ctx->enumeration = enumeration; } else if (strcmp(element_name, "entry") == 0) { if (name == NULL) fail(&ctx->loc, "no entry name given"); entry = create_entry(name, value); version = version_from_since(ctx, since); if (version < ctx->enumeration->since) warn(&ctx->loc, "since version not increasing\n"); ctx->enumeration->since = version; entry->since = version; if (summary) entry->summary = xstrdup(summary); else entry->summary = NULL; wl_list_insert(ctx->enumeration->entry_list.prev, &entry->link); } else if (strcmp(element_name, "description") == 0) { if (summary == NULL) fail(&ctx->loc, "description without summary"); description = xzalloc(sizeof *description); description->summary = xstrdup(summary); if (ctx->message) ctx->message->description = description; else if (ctx->enumeration) ctx->enumeration->description = description; else if (ctx->interface) ctx->interface->description = description; else ctx->protocol->description = description; ctx->description = description; } }
static int give_read_copy (int requester_id, int request_id, int page_number) { int result; pthread_mutex_lock(&locks[page_number]); int owner_id = get_owner(page_number); if (owner_id != thisid) { pthread_mutex_unlock(&locks[page_number]); return -E_INCORRECT_OWNER; } struct PageStatus *page_status = get_page_status(page_number); switch (page_status->status) { case READABLE: { if (requester_id == thisid) { // Status should not be readable without local copy having // read permissions; with these permissions, a page fault // should not be thrown and this should never be called result = -E_INCONSISTENT_STATE; break; } // Transfer page over network to owner_id and tell it it // has PROT_READ access struct Message m = create_message(SEND_PAGE, READING, page_number); memcpy((void *) m.page, (void *) get_pageaddr(page_number), PGSIZE); m.is_response = 1; if (request_id == NO_RESPONSE) { result = E_INCONSISTENT_STATE; break; } m.index = request_id; if ((result = send_to(owner_id, &m)) < 0) break; page_status->status_by_owner[requester_id] = READABLE; result = 0; break; } case MODIFIED: { int modifier = page_status->modifying_owner; if (modifier == requester_id) { // The modifier should have read-write permissions, in which // case a page not fault should not be thrown and this // should never be called. result = -E_INCONSISTENT_STATE; break; } if (modifier != thisid) { // Request page from modifier and tell it to set its // permissions to PROT_READ struct Message m = create_message(REQUEST_PAGE, READING, page_number); // Upon receiving the message we should map the page locally if ((result = send_and_wait_for_response(modifier, &m)) < 0) { break; } // Local page should already be set PROT_READ page_status->status_by_owner[thisid] = READING; } page_status->status_by_owner[modifier] = READING; page_status->modifying_owner = NO_OWNER; page_status->status = READABLE; if (requester_id != thisid) { // Transfer page over network to requester_id and tell it it // has PROT_READ access struct Message m = create_message(SEND_PAGE, READING, page_number); memcpy((void *) m.page, (void *) get_pageaddr(page_number), PGSIZE); m.is_response = 1; if (request_id == NO_RESPONSE) { result = E_INCONSISTENT_STATE; break; } m.index = request_id; result = send_to(requester_id, &m); if (result < 0) break; page_status->status_by_owner[requester_id] = READING; } result = 0; break; } default: printf("Unhandled page status in give_read_copy.\n"); exit(-E_UNHANDLED_PAGE_STATUS); } pthread_mutex_unlock(&locks[page_number]); return result; }
static void cb_adc_available(void) { static uint8_t led_count = 0; static uint32_t timestamp_counter = 0; static uint32_t timestamp_last_frame = 0; static uint16_t missed_adc = 0; static uint16_t high_adc = 0; static uint16_t low_adc = 0xffff; uint16_t missed; uint16_t adc_value; uint16_t dxdt; uint32_t timestamp_ms; uint8_t send_adc_only = 0; #if FPS_SEND_ADC_ONLY send_adc_only = 1; #endif // Get ADC reading for light sensor sc_adc_channel_get(&adc_value, ×tamp_ms); // Check if we missed an ADC reading ++timestamp_counter; missed = timestamp_ms - timestamp_counter; timestamp_counter = timestamp_ms; missed_adc += missed; led_count += missed; if (led_count++ > 100) { led_count = 0; sc_led_toggle(); } // Store lowest and highest values for debugging if (adc_value > high_adc) { high_adc = adc_value; } if (adc_value < low_adc) { low_adc = adc_value; } if (handle_adc(adc_value, timestamp_ms, &dxdt) || send_adc_only) { uint8_t buf[64]; uint8_t len; if (send_adc_only) { len = create_adc_msg(buf, 64, adc_value, timestamp_ms); } else { len = create_message(buf, 64, timestamp_ms, timestamp_ms - timestamp_last_frame, missed_adc, low_adc, high_adc, dxdt); } sc_uart_send_msg(SC_UART_LAST, buf, len); high_adc = 0; low_adc = 0xffff; timestamp_last_frame = timestamp_ms; missed_adc = 0; } }
/** Parse message msg */ static void parse_message( wchar_t *msg, connection_t *src ) { // debug( 3, L"parse_message( %ls );", msg ); if( msg[0] == L'#' ) return; if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR )) { wchar_t *name, *tmp; int exportv = match( msg, SET_EXPORT_STR ); name = msg+(exportv?wcslen(SET_EXPORT_STR):wcslen(SET_STR)); while( wcschr( L"\t ", *name ) ) name++; tmp = wcschr( name, L':' ); if( tmp ) { wchar_t *key; wchar_t *val; key = (wchar_t *)malloc( sizeof( wchar_t)*(tmp-name+1)); memcpy( key, name, sizeof( wchar_t)*(tmp-name)); key[tmp-name]=0; val = tmp+1; val = unescape( val, 0 ); env_universal_common_set( key, val, exportv ); free( val ); free( key ); } else { debug( 1, PARSE_ERR, msg ); } } else if( match( msg, ERASE_STR ) ) { wchar_t *name, *tmp; name = msg+wcslen(ERASE_STR); while( wcschr( L"\t ", *name ) ) name++; tmp = name; while( iswalnum( *tmp ) || *tmp == L'_') tmp++; *tmp = 0; if( !wcslen( name ) ) { debug( 1, PARSE_ERR, msg ); } env_universal_common_remove( name ); if( callback ) { callback( ERASE, name, 0 ); } } else if( match( msg, BARRIER_STR) ) { message_t *msg = create_message( BARRIER_REPLY, 0, 0 ); msg->count = 1; src->unsent->push(msg); try_send_all( src ); } else if( match( msg, BARRIER_REPLY_STR ) ) { if( callback ) { callback( BARRIER_REPLY, 0, 0 ); } } else { debug( 1, PARSE_ERR, msg ); } }
int __send_local(long ticket, unsigned short type, int slot, long value, unsigned short flags) { message *msg = create_message(my_id(), my_id(), ticket, type, slot, value, flags); log_message("send_local", msg); add_message(msg); return 1; }
static int fill_recv_buf() { int retval = 0; fd_set rfds; struct timeval tv; if (sockfd == -1) { debug("sockfd is -1"); if (time(NULL) - last_activity > LAG_INTERVAL) { debug("LAG_INTERVAL has been reached"); log_info("Trying to reconnect..."); sockfd = connect_to_server(); if (sockfd == -1) { log_info("Failed: %s", strerror(errno)); return -1; } else log_info("Succeeded!"); } else { debug("LAG_INTERVAL not reached; sleeping..."); sleep(5); return -1; } } FD_ZERO(&rfds); FD_SET(sockfd, &rfds); tv.tv_sec = 0; tv.tv_usec = 500000; retval = select(sockfd + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { log_err("Error waiting for socket: %s", strerror(errno)); close(sockfd); sockfd = -1; return -1; } else if (!retval) { time_t curr; time(&curr); if (curr - last_activity > LAG_INTERVAL) { debug("appear to have lost connection"); if (!waiting_for_ping) { struct irc_message *ping_msg; debug("sending ping.."); ping_msg = create_message(NULL, "PING", ":ping"); send_msg(ping_msg); free_message(ping_msg); waiting_for_ping = 1; } else if (curr - last_activity > LAG_INTERVAL + PING_WAIT_TIME) { log_info("Lost connection..."); waiting_for_ping = 0; close(sockfd); sockfd = -1; reset(); } } return -1; } recv_buf_size = recv(sockfd, recv_buf, RECV_BUF_LENGTH - 1, 0); if (recv_buf_size == 0) { // connection has been terminated // likely due to ping timeout sockfd = -1; log_info("Connection terminated. Reconnecting.."); return -1; } else if (recv_buf_size == -1) { log_err("Error receiving packets: %s", strerror(errno)); kill_bot(); return -1; } recv_buf[recv_buf_size] = '\0'; recv_buf_pos = recv_buf; time(&last_activity); waiting_for_ping = 0; return 0; }
void mcview_do_search (mcview_t * view) { off_t search_start = 0; gboolean isFound = FALSE; gboolean need_search_again = TRUE; Dlg_head *d = NULL; size_t match_len; if (verbose) { d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string); tty_refresh (); } /*for avoid infinite search loop we need to increase or decrease start offset of search */ if (view->search_start != 0) { if (!view->text_nroff_mode) search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0); else { if (mcview_search_options.backwards) { mcview_nroff_t *nroff; nroff = mcview_nroff_seq_new_num (view, view->search_start); if (mcview_nroff_seq_prev (nroff) != -1) search_start = -(mcview__get_nroff_real_len (view, nroff->index - 1, 2) + nroff->char_width + 1); else search_start = -2; mcview_nroff_seq_free (&nroff); } else { search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2); } search_start += view->search_start; } } if (mcview_search_options.backwards && (int) search_start < 0) search_start = 0; /* Compute the percent steps */ mcview_search_update_steps (view); view->update_activate = 0; tty_enable_interrupt_key (); do { off_t growbufsize; if (view->growbuf_in_use) growbufsize = mcview_growbuf_filesize (view); else growbufsize = view->search->original_len; if (mcview_find (view, search_start, &match_len)) { mcview_search_show_result (view, &d, match_len); need_search_again = FALSE; isFound = TRUE; break; } if (view->search->error_str == NULL) break; search_start = growbufsize - view->search->original_len; if (search_start <= 0) { search_start = 0; break; } } while (mcview_may_still_grow (view)); if (view->search_start != 0 && !isFound && need_search_again && !mcview_search_options.backwards) { int result; mcview_update (view); result = query_dialog (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"), _("&No")); if (result != 0) isFound = TRUE; else search_start = 0; } if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len)) { mcview_search_show_result (view, &d, match_len); isFound = TRUE; } tty_disable_interrupt_key (); if (verbose) { dlg_run_done (d); destroy_dlg (d); } if (!isFound && view->search->error_str != NULL) message (D_NORMAL, _("Search"), "%s", view->search->error_str); view->dirty++; mcview_update (view); }
int start_command(JNIEnv *env, jclass clazz __attribute__((unused)), jstring jhandler, jstring jcmd) { char status; char *pos, *start, *end, *rpos, *wpos; const char *utf; jstring *utf_parent; handler *h; uint32_t msg_size; // big enought to check for uint16_t overflow int id; size_t arg_len, escapes; struct cmd_start_info *start_info; message *m; child_node *c; id = -1; m=NULL; c=NULL; if(!authenticated()) { LOGE("%s: not authenticated", __func__); return -1; } utf = (*env)->GetStringUTFChars(env, jhandler, NULL); utf_parent = &jhandler; if(!utf) { LOGE("%s: cannot get handler name", __func__); goto jni_error; } arg_len = (*env)->GetStringUTFLength(env, jhandler); if(!arg_len) { LOGE("%s: empty handler name", __func__); goto jni_error; } arg_len++; // test even the '\0' for(h=(handler *) handlers.list.head;h && strncmp(utf, h->name, arg_len);h=(handler *) h->next); if(!h) { LOGE("%s: handler \"%s\" not found", __func__, utf); goto exit; } (*env)->ReleaseStringUTFChars(env, jhandler, utf); utf = (*env)->GetStringUTFChars(env, jcmd, NULL); utf_parent = &jcmd; if(!utf) { LOGE("%s: cannot get command string", __func__); goto jni_error; } LOGD("%s: parsing \"%s\"", __func__, utf); msg_size = sizeof(struct cmd_start_info); m = create_message(get_sequence(&ctrl_seq, &ctrl_seq_lock), msg_size, CTRL_ID); if(!m) { LOGE("%s: cannot create messages", __func__); goto exit; } start_info = (struct cmd_start_info *) m->data; start_info->cmd_action = CMD_START; start_info->hid = h->id; status = 0; arg_len = 0; escapes = 0; start = end = NULL; for(pos=(char *) utf;!(status & END_OF_STRING);pos++) { // string status parser switch (*pos) { case '"': if(status & ESCAPE_FOUND) { escapes++; } else if(status & (INSIDE_SINGLE_QUOTE)) { // copy it as a normal char } else if(status & INSIDE_DOUBLE_QUOTE) { status &= ~INSIDE_DOUBLE_QUOTE; end = pos; } else { status |= INSIDE_DOUBLE_QUOTE; } break; case '\'': if(status & ESCAPE_FOUND) { escapes++; } else if(status & INSIDE_DOUBLE_QUOTE) { // copy it as a normal char } else if(status & INSIDE_SINGLE_QUOTE) { status &= ~INSIDE_SINGLE_QUOTE; end = pos; } else { status |= INSIDE_SINGLE_QUOTE; } break; case '\\': if(status & ESCAPE_FOUND) { // copy it as normal char escapes++; } else { status |= ESCAPE_FOUND; continue; } break; case ' ': // if(isspace(*pos)) case '\t': if(status & ESCAPE_FOUND) { escapes++; } else if(!status && start) { end=pos; } break; case '\0': status |= END_OF_STRING; end=pos; break; default: if(!start) start=pos; } status &= ~ESCAPE_FOUND; // copy the arg if found if(start && end) { LOGD("%s: argument found: start=%d, end=%d", __func__, (start-utf), (end-utf)); arg_len=(end-start); arg_len-= escapes; msg_size+=arg_len + 1; if(msg_size > UINT16_MAX) { LOGW("%s: command too long: \"%s\"", __func__, utf); goto exit; } m->data = realloc(m->data, msg_size); if(!m->data) { LOGE("%s: realloc: %s", __func__, strerror(errno)); goto exit; } wpos = m->data + m->head.size; for(rpos=start;rpos<end;rpos++) { if(status & ESCAPE_FOUND) { status &= ~ESCAPE_FOUND; if( *rpos != '\\' && *rpos != '"' && *rpos != '\'' && *rpos != ' ' && *rpos != '\t') { // unrecognized escape sequence, copy the backslash as it is. *wpos = '\\'; wpos++; } } else if(*rpos == '\\') { status |= ESCAPE_FOUND; continue; } *wpos=*rpos; wpos++; } *(m->data + msg_size -1) = '\0'; m->head.size = msg_size; start = end = NULL; escapes = 0; } } // create child c = create_child(m->head.seq); if(!c) { LOGE("%s: cannot craete child", __func__); goto exit; } c->handler = h; // add child to list pthread_mutex_lock(&(children.control.mutex)); list_add(&(children.list), (node *) c); pthread_mutex_unlock(&(children.control.mutex)); // send message to dSploitd pthread_mutex_lock(&write_lock); // OPTIMIZATION: use escapes to store return value for later check escapes = send_message(sockfd, m); pthread_mutex_unlock(&write_lock); if(escapes) { LOGE("%s: cannot send messages", __func__); goto exit; } // wait for CMD_STARTED or CMD_FAIL pthread_mutex_lock(&(children.control.mutex)); while(c->seq && children.control.active) pthread_cond_wait(&(children.control.cond), &(children.control.mutex)); if(c->id == CTRL_ID || c->seq) { // command failed list_del(&(children.list), (node *) c); } else { id = c->id; } c->pending = 0; pthread_mutex_unlock(&(children.control.mutex)); pthread_cond_broadcast(&(children.control.cond)); if(id != -1) { LOGI("%s: child #%d started", __func__, id); } else if(c->seq) { LOGW("%s: pending child cancelled", __func__); } else { LOGW("%s: cannot start command", __func__); } goto exit; jni_error: if((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } exit: if(c && id==-1) { pthread_mutex_lock(&(children.control.mutex)); list_del(&(children.list), (node *) c); pthread_mutex_unlock(&(children.control.mutex)); pthread_cond_broadcast(&(children.control.cond)); free_child(c); } if(m) free_message(m); if(utf) (*env)->ReleaseStringUTFChars(env, *utf_parent, utf); return id; }
void GameArbiter::process_command(Message *command) { switch (command->type) { case UnitMove: { auto cmd = dynamic_cast<UnitMoveMessage *>(command); int stack_id = cmd->data1; IntSet units = cmd->data2; Path& path = cmd->data3; int target_id = cmd->data4; UnitStack::pointer stack = game->stacks.get(stack_id); if (units.empty() || !stack->has_units(units) || path.empty()) { throw DataError() << "Invalid UnitMove message"; } /* Check that the move is allowed; shorten it if necessary */ Point end_pos = path.back(); UnitStack::pointer end_stack = game->level.tiles[end_pos].stack; int end_stack_id = end_stack ? end_stack->id : 0; if (end_stack_id != target_id) { path.pop_back(); target_id = 0; } MovementModel movement(game); UnitStack::pointer selected_stack = stack->copy_subset(units); unsigned int allowed_steps = movement.check_path(*selected_stack, path); bool truncated = allowed_steps < path.size(); int attack_target_id = target_id; if (truncated) target_id = 0; path.resize(allowed_steps); if (!path.empty()) { end_pos = path.back(); /* Generate updates. */ Faction::pointer faction = stack->owner; bool move = units.size() == stack->units.size() && target_id == 0; bool split = units.size() < stack->units.size() && target_id == 0; bool merge = units.size() == stack->units.size() && target_id != 0; UnitStack::pointer target = game->stacks.find(target_id); if (move) target_id = stack_id; if (split) target_id = game->get_free_stack_id(); // Send the moves for (auto iter = path.begin(); iter != path.end(); iter++) { emit(create_message(MoveUnits, stack_id, units, *iter)); } // If the stack is splitting to a new empty position, create a stack there if (split) { emit(create_message(CreateStack, target_id, end_pos, faction->id)); } emit(create_message(TransferUnits, stack_id, units, path, target_id)); // If the whole stack merged with an existing one, destroy it if (merge) { emit(create_message(DestroyStack, stack_id)); } } else { end_pos = stack->position; } UnitStack::pointer attack_target = game->stacks.find(attack_target_id); bool attack = attack_target && (attack_target->owner != stack->owner); if (attack) { BOOST_LOG_TRIVIAL(debug) << "Attack!"; Point target_point = attack_target->position; Point attacking_point = end_pos; Battle battle(game, target_point, attacking_point); battle.run(); emit(create_message(DoBattle, end_stack_id, target_point, battle.moves)); } } break; case FactionReady: { auto cmd = dynamic_cast<FactionReadyMessage *>(command); int faction_id = cmd->data1; bool ready = cmd->data2; if (game->mark_faction_ready(faction_id, ready)) { emit(create_message(FactionReady, faction_id, ready)); } if (game->all_factions_ready()) { emit(create_message(TurnEnd)); // process turn end spawn_units(); game->turn_number++; emit(create_message(TurnBegin, game->turn_number)); } } break; case Chat: { auto chat_msg = dynamic_cast<ChatMessage *>(command); emit(create_message(Chat, chat_msg->data)); } break; case SetLevelData: case CreateStructure: case DestroyStructure: { emit(command->shared_from_this()); } break; default: break; } }
int start_command(JNIEnv *env, jclass clazz __attribute__((unused)), jstring jhandler, jstring jcmd, jobjectArray jenv) { const char *utf; handler *h; int id; struct cmd_start_info *start_info; message *m; child_node *c; id = -1; m=NULL; c=NULL; utf=NULL; if(!authenticated()) { LOGE("%s: not authenticated", __func__); return -1; } if(!jhandler) { LOGE("%s: handler cannot be null", __func__); return -1; } utf = (*env)->GetStringUTFChars(env, jhandler, NULL); if(!utf) { LOGE("%s: cannot get handler name", __func__); goto jni_error; } h = get_handler_by_name(utf); if(!h) { LOGE("%s: handler \"%s\" not found", __func__, utf); goto exit; } (*env)->ReleaseStringUTFChars(env, jhandler, utf); utf=NULL; m = create_message(get_sequence(&ctrl_seq, &ctrl_seq_lock), sizeof(struct cmd_start_info), CTRL_ID); if(!m) { LOGE("%s: cannot create messages", __func__); goto exit; } start_info = (struct cmd_start_info *) m->data; start_info->cmd_action = CMD_START; start_info->hid = h->id; if(jcmd && parse_cmd(env, h, jcmd, m)) { LOGE("%s: cannot parse command", __func__); goto exit; } if(jenv && parse_env(env, jenv, m)) { LOGE("%s: cannot parse environment", __func__); goto exit; } // create child c = create_child(m->head.seq); if(!c) { LOGE("%s: cannot craete child", __func__); goto exit; } c->handler = h; // add child to list pthread_mutex_lock(&(children.control.mutex)); list_add(&(children.list), (node *) c); pthread_mutex_unlock(&(children.control.mutex)); // send message to cSploitd pthread_mutex_lock(&write_lock); // OPTIMIZATION: use id to store return value for later check id = send_message(sockfd, m); pthread_mutex_unlock(&write_lock); if(id) { LOGE("%s: cannot send messages", __func__); // mark it as failed c->id = CTRL_ID; c->seq = 0; } id=-1; // wait for CMD_STARTED or CMD_FAIL pthread_mutex_lock(&(children.control.mutex)); while(c->seq && children.control.active) pthread_cond_wait(&(children.control.cond), &(children.control.mutex)); if(c->id == CTRL_ID || c->seq) { // command failed list_del(&(children.list), (node *) c); } else { id = c->id; } c->pending = 0; pthread_mutex_unlock(&(children.control.mutex)); pthread_cond_broadcast(&(children.control.cond)); if(id != -1) { LOGI("%s: child #%d started", __func__, id); } else if(c->seq) { LOGW("%s: pending child cancelled", __func__); } else { LOGW("%s: cannot start command", __func__); } goto exit; jni_error: if((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } exit: if(m) free_message(m); if(utf) (*env)->ReleaseStringUTFChars(env, jhandler, utf); return id; }
void SocketSPI::send_message(const int code, wstring data) { char * msg = create_message(code, encoder.decode(data).c_str()); send(this->client_sfd, (void *) msg, strlen(msg), 0); }