static inline void psock_lost_connection(FAR struct socket *psock, FAR struct tcp_conn_s *conn) { FAR sq_entry_t *entry; FAR sq_entry_t *next; /* Do not allow any further callbacks */ psock->s_sndcb->flags = 0; psock->s_sndcb->event = NULL; /* Free all queued write buffers */ for (entry = sq_peek(&conn->unacked_q); entry; entry = next) { next = sq_next(entry); tcp_wrbuffer_release((FAR struct tcp_wrbuffer_s *)entry); } for (entry = sq_peek(&conn->write_q); entry; entry = next) { next = sq_next(entry); tcp_wrbuffer_release((FAR struct tcp_wrbuffer_s *)entry); } /* Reset write buffering variables */ sq_init(&conn->unacked_q); sq_init(&conn->write_q); conn->sent = 0; }
//------------------------------------------------------------------------------ void SN_API getTable(HSQUIRRELVM vm, Variant & out_v, SQInteger index) { out_v.setDictionary(); Variant::Dictionary & d = out_v.getDictionary(); sq_push(vm, index); sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, -2))) { if (sq_gettype(vm, -2) == OT_STRING) { const SQChar * key = nullptr; sq_getstring(vm, -2, &key); Variant & val = d[key]; getVariant(vm, val, -1); } else { SN_WARNING("non-string keys in tables are not supported by getVariant"); } sq_pop(vm, 2); } sq_pop(vm, 2); // Pop iterator and table }
template <> inline Array *GetParam(ForceType<Array *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQObject obj; sq_getstackobj(vm, index, &obj); sq_pushobject(vm, obj); sq_pushnull(vm); SmallVector<int32, 2> data; while (SQ_SUCCEEDED(sq_next(vm, -2))) { SQInteger tmp; if (SQ_SUCCEEDED(sq_getinteger(vm, -1, &tmp))) { *data.Append() = (int32)tmp; } else { sq_pop(vm, 4); throw sq_throwerror(vm, _SC("a member of an array used as parameter to a function is not numeric")); } sq_pop(vm, 2); } sq_pop(vm, 2); Array *arr = (Array*)MallocT<byte>(sizeof(Array) + sizeof(int32) * data.Length()); arr->size = data.Length(); memcpy(arr->array, data.Begin(), sizeof(int32) * data.Length()); *ptr->Append() = arr; return arr; }
static void psock_insert_segment(FAR struct tcp_wrbuffer_s *wrb, FAR sq_queue_t *q) { sq_entry_t *entry = (sq_entry_t*)wrb; sq_entry_t *insert = NULL; sq_entry_t *itr; for (itr = sq_peek(q); itr; itr = sq_next(itr)) { FAR struct tcp_wrbuffer_s *wrb0 = (FAR struct tcp_wrbuffer_s*)itr; if (WRB_SEQNO(wrb0) < WRB_SEQNO(wrb)) { insert = itr; } else { break; } } if (insert) { sq_addafter(insert, entry, q); } else { sq_addfirst(entry, q); } }
//------------------------------------------------------------------------------ void SN_API getArray(HSQUIRRELVM vm, Variant & out_v, SQInteger index) { out_v.setArray(); Variant::Array & a = out_v.getArray(); SQInteger len = sq_getsize(vm, index); SN_ASSERT(len >= 0, "Invalid array size"); if (len > 0) { a.resize(len); s32 i = 0; sq_push(vm, index); sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, -2))) { // -1 is the value and -2 is the key sq_getinteger(vm, -2, &i); Variant & val = a[i]; getVariant(vm, val, -1); sq_pop(vm, 2); //pops key and val before the next iteration } sq_pop(vm, 2); // Pop the null iterator and array } }
perf_counter_t perf_alloc_once(enum perf_counter_type type, const char *name) { pthread_mutex_lock(&perf_counters_mutex); perf_counter_t handle = (perf_counter_t)sq_peek(&perf_counters); while (handle != NULL) { if (!strcmp(handle->name, name)) { if (type == handle->type) { /* they are the same counter */ pthread_mutex_unlock(&perf_counters_mutex); return handle; } else { /* same name but different type, assuming this is an error and not intended */ pthread_mutex_unlock(&perf_counters_mutex); return NULL; } } handle = (perf_counter_t)sq_next(&handle->link); } pthread_mutex_unlock(&perf_counters_mutex); /* if the execution reaches here, no existing counter of that name was found */ return perf_alloc(type, name); }
std::vector<std::string> ConsoleImpl::get_roottable() { std::vector<std::string> roottable; HSQUIRRELVM v = script_manager->get_vm(); sq_pushroottable(v); //push your table/array here sq_pushnull(v); //null iterator while(SQ_SUCCEEDED(sq_next(v,-2))) { //here -1 is the value and -2 is the key const SQChar *s; if (SQ_SUCCEEDED(sq_getstring(v,-2, &s))) { roottable.push_back((char*)s); } else { console << "Unknown key type for element" << std::endl; } sq_pop(v,2); //pops key and val before the nex iteration } sq_pop(v, 1); return roottable; }
static void send_insert_seqment(FAR struct uip_wrbuffer_s *segment, FAR sq_queue_t *q) { sq_entry_t *entry = (sq_entry_t*)segment; sq_entry_t *insert = NULL; sq_entry_t *itr; for (itr = sq_peek(q); itr; itr = sq_next(itr)) { FAR struct uip_wrbuffer_s *segment0 = (FAR struct uip_wrbuffer_s*)itr; if (segment0->wb_seqno < segment->wb_seqno) { insert = itr; } else { break; } } if (insert) { sq_addafter(insert, entry, q); } else { sq_addfirst(entry, q); } }
static void hrt_call_enter(struct hrt_call *entry) { struct hrt_call *call, *next; call = (struct hrt_call *)sq_peek(&callout_queue); if ((call == NULL) || (entry->deadline < call->deadline)) { sq_addfirst(&entry->link, &callout_queue); //lldbg("call enter at head, reschedule\n"); /* we changed the next deadline, reschedule the timer event */ hrt_call_reschedule(); } else { do { next = (struct hrt_call *)sq_next(&call->link); if ((next == NULL) || (entry->deadline < next->deadline)) { //lldbg("call enter after head\n"); sq_addafter(&call->link, &entry->link, &callout_queue); break; } } while ((call = next) != NULL); } //lldbg("scheduled\n"); }
int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn) { FAR struct uip_backlog_s *bls; FAR struct uip_blcontainer_s *blc; FAR struct uip_blcontainer_s *prev; nllvdbg("conn=%p blconn=%p\n", conn, blconn); #ifdef CONFIG_DEBUG if (!conn) { return -EINVAL; } #endif bls = conn->backlog; if (bls) { /* Find the container hold the connection */ for (blc = (FAR struct uip_blcontainer_s *)sq_peek(&bls->bl_pending), prev = NULL; blc; prev = blc, blc = (FAR struct uip_blcontainer_s *)sq_next(&blc->bc_node)) { if (blc->bc_conn == blconn) { if (prev) { /* Remove the a container from the middle of the list of * pending connections */ (void)sq_remafter(&prev->bc_node, &bls->bl_pending); } else { /* Remove the a container from the head of the list of * pending connections */ (void)sq_remfirst(&bls->bl_pending); } /* Put container in the free list */ blc->bc_conn = NULL; sq_addlast(&blc->bc_node, &bls->bl_free); return OK; } } nlldbg("Failed to find pending connection\n"); return -EINVAL; } return OK; }
void perf_print_all(int fd) { perf_counter_t handle = (perf_counter_t)sq_peek(&perf_counters); while (handle != NULL) { perf_print_counter_fd(fd, handle); handle = (perf_counter_t)sq_next(&handle->link); } }
BOOL SquirrelObject::Next(SquirrelObject &key,SquirrelObject &val) { if(SQ_SUCCEEDED(sq_next(m_Vm.GetVMPtr(),-2))) { key.AttachToStackObject(-2); val.AttachToStackObject(-1); sq_pop(m_Vm.GetVMPtr(),2); return TRUE; } return FALSE; }
SQInteger Sq_Interpolate(HSQUIRRELVM v) { const SQChar *Str, *WordString; char Out[4096]; sq_getstring(v, 2, &Str); sq_getstring(v, 3, &WordString); char *Poke = Out; const char *Peek = Str; char WordBuff[strlen(Str)+1]; const char *Word[32]; const char *WordEol[32]; XChatTokenize(WordString, WordBuff, Word, WordEol, 32, TOKENIZE_MULTI_WORD); while(*Peek) { int Span = strcspn(Peek, "%&"); memcpy(Poke, Peek, Span); Poke += Span; Peek += Span; if(*Peek == '%' || *Peek == '&') { char Extra = Peek[1]; if(Extra == '%') *(Poke++) = '%'; else if(Extra == '&') *(Poke++) = '&'; else { if(isdigit(Extra)) { int WhichWord = Extra - '1'; strcpy(Poke, (*Peek=='%')?Word[WhichWord]:WordEol[WhichWord]); Poke = strrchr(Poke, 0); } else { // look in the list of extra words int top = sq_gettop(v);; sq_pushnull(v); //null iterator while(SQ_SUCCEEDED(sq_next(v,-2))) { const SQChar *ThisWord; sq_getstring(v, -1, &ThisWord); if(ThisWord[0]==Extra) { strcpy(Poke, ThisWord+1); Poke = strrchr(Poke, 0); break; } sq_pop(v,2); } sq_pop(v,1); //pops the null iterator sq_settop(v, top); } } Peek+= 2; } } *Poke = 0; sq_pushstring(v, Out, -1); return 1; }
void perf_print_all(int fd) { pthread_mutex_lock(&perf_counters_mutex); perf_counter_t handle = (perf_counter_t)sq_peek(&perf_counters); while (handle != NULL) { perf_print_counter_fd(fd, handle); handle = (perf_counter_t)sq_next(&handle->link); } pthread_mutex_unlock(&perf_counters_mutex); }
void perf_iterate_all(perf_callback cb, void *user) { pthread_mutex_lock(&perf_counters_mutex); perf_counter_t handle = (perf_counter_t)sq_peek(&perf_counters); while (handle != NULL) { cb(handle, user); handle = (perf_counter_t)sq_next(&handle->link); } pthread_mutex_unlock(&perf_counters_mutex); }
void perf_reset_all(void) { perf_counter_t handle = (perf_counter_t)sq_peek(&perf_counters); while (handle != NULL) { perf_reset(handle); handle = (perf_counter_t)sq_next(&handle->link); } for (int i = 0; i <= latency_bucket_count; i++) { latency_counters[i] = 0; } }
static void handle_queued_events(struct conman_client_s *client, sq_queue_t *qevents) { struct queued_event_s *item; item = (void *)sq_peek(qevents); while (item) { struct queued_event_s *curr = item; item = (void *)sq_next(&item->node); client->event_callback(client, curr->type, curr->payload, curr->payloadlen, client->event_priv); free(curr->payload); free(curr); } }
SQInteger AIInfo::AddLabels(HSQUIRRELVM vm) { const SQChar *sq_setting_name; if (SQ_FAILED(sq_getstring(vm, -2, &sq_setting_name))) return SQ_ERROR; const char *setting_name = SQ2OTTD(sq_setting_name); AIConfigItem *config = NULL; for (AIConfigItemList::iterator it = this->config_list.begin(); it != this->config_list.end(); it++) { if (strcmp((*it).name, setting_name) == 0) config = &(*it); } if (config == NULL) { char error[1024]; snprintf(error, sizeof(error), "Trying to add labels for non-defined setting '%s'", setting_name); this->engine->ThrowError(error); return SQ_ERROR; } if (config->labels != NULL) return SQ_ERROR; config->labels = new LabelMapping; /* Read the table and find all labels */ sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, -2))) { const SQChar *sq_key; const SQChar *sq_label; if (SQ_FAILED(sq_getstring(vm, -2, &sq_key))) return SQ_ERROR; if (SQ_FAILED(sq_getstring(vm, -1, &sq_label))) return SQ_ERROR; /* Because squirrel doesn't support identifiers starting with a digit, * we skip the first character. */ const char *key_string = SQ2OTTD(sq_key); int key = atoi(key_string + 1); const char *label = SQ2OTTD(sq_label); /* !Contains() prevents strdup from leaking. */ if (!config->labels->Contains(key)) config->labels->Insert(key, strdup(label)); sq_pop(vm, 2); } sq_pop(vm, 1); return 0; }
static inline void pm_changeall(enum pm_state_e newstate) { FAR sq_entry_t *entry; /* Visit each registered callback structure. */ for (entry = sq_peek(&g_pmglobals.registry); entry; entry = sq_next(entry)) { /* Is the notification callback supported? */ FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; if (cb->notify) { /* Yes.. notify the driver */ cb->notify(cb, newstate); } } }
/**************************************************************************** * Name: ubgps_publish_event * * Description: * Publish event to registered callbacks * * Input Parameters: * gps - GPS object * event - Pointer to published event * * Returned Values: * Status * ****************************************************************************/ void ubgps_publish_event(struct ubgps_s * const gps, struct gps_event_s const * const event) { struct gps_callback_entry_s const * cb; DEBUGASSERT(gps && event); /* Check if any callback is interested of this event */ if (!(gps->callback_event_mask & event->id)) return; cb = (struct gps_callback_entry_s *)sq_peek(&gps->callbacks); while (cb) { if ((cb->event_mask & event->id) && cb->callback) cb->callback(event, cb->priv); cb = (struct gps_callback_entry_s *)sq_next(&cb->entry); } }
void __conman_send_boardcast_event(struct conman_s *conman, enum conman_msgs_ids type, const void *payload, size_t payloadlen) { struct conman_sd_entry_s *client; struct conman_resp_hdr hdr = {}; int send_count = 0; int ret; hdr.head.id = type; hdr.head.len = payloadlen; hdr.respval = CONMAN_RESP_EVENT; for (client = (struct conman_sd_entry_s *)sq_peek(&conman->server.sds); client != NULL; client = (struct conman_sd_entry_s *)sq_next(&client->entry)) { if (!client->events_enabled) { continue; } ret = __conman_util_block_write(client->sd, &hdr, sizeof(hdr)); if (ret < 0) { continue; } ret = __conman_util_block_write(client->sd, payload, hdr.head.len); if (ret < 0) { continue; } send_count++; } conman_dbg("send boardcast event (type=%d) to %d clients.\n", type, send_count); }
void __ubgps_gc_callbacks(struct ubgps_s * const gps) { struct gps_callback_entry_s * cb, * cbnext; /* Search for callback in queue */ cb = (struct gps_callback_entry_s *)sq_peek(&gps->callbacks); while (cb) { /* Save next callback entry */ cbnext = (struct gps_callback_entry_s *)sq_next(&cb->entry); if (cb->event_mask == 0) { /* Free unactive callback. */ sq_rem(&cb->entry, &gps->callbacks); free(cb); } cb = cbnext; } }
static int pm_prepall(enum pm_state_e newstate) { FAR sq_entry_t *entry; int ret = OK; /* Visit each registered callback structure. */ for (entry = sq_peek(&g_pmglobals.registry); entry && ret == OK; entry = sq_next(entry)) { /* Is the prepare callback supported? */ FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry; if (cb->prepare) { /* Yes.. prepare the driver */ ret = cb->prepare(cb, newstate); } } return ret; }
std::vector<std::string> get_table_keys(HSQUIRRELVM vm) { std::vector<std::string> keys; sq_pushnull(vm); while(SQ_SUCCEEDED(sq_next(vm, -2))) { //here -1 is the value and -2 is the key const char* result; if(SQ_FAILED(sq_getstring(vm, -2, &result))) { throw scripting::SquirrelError(vm, "Couldn't get string value for key"); } else { keys.push_back(result); } // pops key and val before the next iteration sq_pop(vm, 2); } return keys; }
/* static */ bool ScriptInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test) { if (max_depth == 0) { ScriptLog::Error("Savedata can only be nested to 25 deep. No data saved."); // SQUIRREL_MAX_DEPTH = 25 return false; } switch (sq_gettype(vm, index)) { case OT_INTEGER: { if (!test) { _script_sl_byte = SQSL_INT; SlObject(NULL, _script_byte); } SQInteger res; sq_getinteger(vm, index, &res); if (!test) { int value = (int)res; SlArray(&value, 1, SLE_INT32); } return true; } case OT_STRING: { if (!test) { _script_sl_byte = SQSL_STRING; SlObject(NULL, _script_byte); } const SQChar *res; sq_getstring(vm, index, &res); /* @bug if a string longer than 512 characters is given to SQ2OTTD, the * internal buffer overflows. */ const char *buf = SQ2OTTD(res); size_t len = strlen(buf) + 1; if (len >= 255) { ScriptLog::Error("Maximum string length is 254 chars. No data saved."); return false; } if (!test) { _script_sl_byte = (byte)len; SlObject(NULL, _script_byte); SlArray(const_cast<char *>(buf), len, SLE_CHAR); } return true; } case OT_ARRAY: { if (!test) { _script_sl_byte = SQSL_ARRAY; SlObject(NULL, _script_byte); } sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { /* Store the value */ bool res = SaveObject(vm, -1, max_depth - 1, test); sq_pop(vm, 2); if (!res) { sq_pop(vm, 1); return false; } } sq_pop(vm, 1); if (!test) { _script_sl_byte = SQSL_ARRAY_TABLE_END; SlObject(NULL, _script_byte); } return true; } case OT_TABLE: { if (!test) { _script_sl_byte = SQSL_TABLE; SlObject(NULL, _script_byte); } sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { /* Store the key + value */ bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test); sq_pop(vm, 2); if (!res) { sq_pop(vm, 1); return false; } } sq_pop(vm, 1); if (!test) { _script_sl_byte = SQSL_ARRAY_TABLE_END; SlObject(NULL, _script_byte); } return true; } case OT_BOOL: { if (!test) { _script_sl_byte = SQSL_BOOL; SlObject(NULL, _script_byte); } SQBool res; sq_getbool(vm, index, &res); if (!test) { _script_sl_byte = res ? 1 : 0; SlObject(NULL, _script_byte); } return true; } case OT_NULL: { if (!test) { _script_sl_byte = SQSL_NULL; SlObject(NULL, _script_byte); } return true; } default: ScriptLog::Error("You tried to save an unsupported type. No data saved."); return false; } }
/* static */ bool ScriptAdmin::MakeJSON(HSQUIRRELVM vm, SQInteger index, int max_depth, std::string &data) { if (max_depth == 0) { ScriptLog::Error("Send parameters can only be nested to 25 deep. No data sent."); // SQUIRREL_MAX_DEPTH = 25 return false; } switch (sq_gettype(vm, index)) { case OT_INTEGER: { SQInteger res; sq_getinteger(vm, index, &res); char buf[10]; snprintf(buf, sizeof(buf), "%d", (int32)res); data = buf; return true; } case OT_STRING: { const SQChar *res; sq_getstring(vm, index, &res); /* @bug if a string longer than 512 characters is given to SQ2OTTD, the * internal buffer overflows. */ const char *buf = SQ2OTTD(res); size_t len = strlen(buf) + 1; if (len >= 255) { ScriptLog::Error("Maximum string length is 254 chars. No data sent."); return false; } data = std::string("\"") + buf + "\""; return true; } case OT_ARRAY: { data = "[ "; bool first = true; sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { if (!first) data += ", "; if (first) first = false; std::string tmp; bool res = MakeJSON(vm, -1, max_depth - 1, tmp); sq_pop(vm, 2); if (!res) { sq_pop(vm, 1); return false; } data += tmp; } sq_pop(vm, 1); data += " ]"; return true; } case OT_TABLE: { data = "{ "; bool first = true; sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { if (!first) data += ", "; if (first) first = false; std::string key; std::string value; /* Store the key + value */ bool res = MakeJSON(vm, -2, max_depth - 1, key) && MakeJSON(vm, -1, max_depth - 1, value); sq_pop(vm, 2); if (!res) { sq_pop(vm, 1); return false; } data += key + ": " + value; } sq_pop(vm, 1); data += " }"; return true; } case OT_BOOL: { SQBool res; sq_getbool(vm, index, &res); if (res) { data = "true"; return true; } data = "false"; return true; } case OT_NULL: { data = "null"; return true; } default: ScriptLog::Error("You tried to send an unsupported type. No data sent."); return false; } }
/* ** Copies values from State src to State dst. */ static SQRESULT copy_values_between_vms (HSQUIRRELVM dst, HSQUIRRELVM src, int argc, int argIdx) { SQRESULT _rc_; sq_reservestack(dst, argc + 20); argc += argIdx; //we will work with argc args starting at argIdx for (; argIdx < argc; argIdx++) { switch (sq_gettype(src, argIdx)) { case OT_INTEGER: SQ_GET_INTEGER(src, argIdx, vint); sq_pushinteger(dst, vint); break; case OT_FLOAT: SQ_GET_FLOAT(src, argIdx, vfloat); sq_pushfloat (dst, vfloat); break; case OT_BOOL: SQ_GET_BOOL(src, argIdx, vbool); sq_pushbool (dst, vbool); break; case OT_STRING: { SQ_GET_STRING(src, argIdx, vstr) sq_pushstring (dst, vstr, vstr_size); } break; case OT_ARRAY: { SQInteger size = sq_getsize(src, argIdx); sq_newarray(dst, size); for(SQInteger i=0; i<size; ++i) { sq_pushinteger(src, i); sq_get(src, -2); sq_pushinteger(dst, i); if(copy_values_between_vms(dst, src, 1, sq_gettop(src)) != SQ_OK) return SQ_ERROR; sq_poptop(src); sq_set(dst, -3); } } break; case OT_TABLE: { sq_newtable(dst); sq_pushnull(src); while(sq_next(src, -2) == SQ_OK) { SQInteger src_top = sq_gettop(src); if(copy_values_between_vms(dst, src, 1, src_top-1) != SQ_OK || copy_values_between_vms(dst, src, 1, src_top) != SQ_OK) return SQ_ERROR; sq_newslot(dst, -3, SQFalse); sq_pop(src, 2); } sq_pop(src,1); } break; case OT_USERPOINTER: { SQUserPointer ptr; sq_getuserpointer(src, argIdx, &ptr); sq_pushuserpointer(dst, ptr); } break; case OT_NULL: sq_pushnull(dst); break; default: return SQ_ERROR; } } return SQ_OK; }
static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; FAR struct socket *psock = (FAR struct socket *)pvpriv; nllvdbg("flags: %04x\n", flags); /* If this packet contains an acknowledgement, then update the count of * acknowledged bytes. */ if ((flags & TCP_ACKDATA) != 0) { FAR struct tcp_wrbuffer_s *wrb; FAR sq_entry_t *entry; FAR sq_entry_t *next; uint32_t ackno; ackno = tcp_getsequence(TCPBUF->ackno); nllvdbg("ACK: ackno=%u flags=%04x\n", ackno, flags); /* Look at every write buffer in the unacked_q. The unacked_q * holds write buffers that have been entirely sent, but which * have not yet been ACKed. */ for (entry = sq_peek(&conn->unacked_q); entry; entry = next) { uint32_t lastseq; /* Check of some or all of this write buffer has been ACKed. */ next = sq_next(entry); wrb = (FAR struct tcp_wrbuffer_s*)entry; /* If the ACKed sequence number is greater than the start * sequence number of the write buffer, then some or all of * the write buffer has been ACKed. */ if (ackno > WRB_SEQNO(wrb)) { /* Get the sequence number at the end of the data */ lastseq = WRB_SEQNO(wrb) + WRB_PKTLEN(wrb); nllvdbg("ACK: wrb=%p seqno=%u lastseq=%u pktlen=%u ackno=%u\n", wrb, WRB_SEQNO(wrb), lastseq, WRB_PKTLEN(wrb), ackno); /* Has the entire buffer been ACKed? */ if (ackno >= lastseq) { nllvdbg("ACK: wrb=%p Freeing write buffer\n", wrb); /* Yes... Remove the write buffer from ACK waiting queue */ sq_rem(entry, &conn->unacked_q); /* And return the write buffer to the pool of free buffers */ tcp_wrbuffer_release(wrb); } else { unsigned int trimlen; /* No, then just trim the ACKed bytes from the beginning * of the write buffer. This will free up some I/O buffers * that can be reused while are still sending the last * buffers in the chain. */ trimlen = ackno - WRB_SEQNO(wrb); if (trimlen > WRB_SENT(wrb)) { /* More data has been ACKed then we have sent? */ trimlen = WRB_SENT(wrb); } nllvdbg("ACK: wrb=%p trim %u bytes\n", wrb, trimlen); WRB_TRIM(wrb, trimlen); WRB_SEQNO(wrb) = ackno; WRB_SENT(wrb) -= trimlen; /* Set the new sequence number for what remains */ nllvdbg("ACK: wrb=%p seqno=%u pktlen=%u\n", wrb, WRB_SEQNO(wrb), WRB_PKTLEN(wrb)); } } } /* A special case is the head of the write_q which may be partially * sent and so can still have un-ACKed bytes that could get ACKed * before the entire write buffer has even been sent. */ wrb = (FAR struct tcp_wrbuffer_s*)sq_peek(&conn->write_q); if (wrb && WRB_SENT(wrb) > 0 && ackno > WRB_SEQNO(wrb)) { uint32_t nacked; /* Number of bytes that were ACKed */ nacked = ackno - WRB_SEQNO(wrb); if (nacked > WRB_SENT(wrb)) { /* More data has been ACKed then we have sent? ASSERT? */ nacked = WRB_SENT(wrb); } nllvdbg("ACK: wrb=%p seqno=%u nacked=%u sent=%u ackno=%u\n", wrb, WRB_SEQNO(wrb), nacked, WRB_SENT(wrb), ackno); /* Trim the ACKed bytes from the beginning of the write buffer. */ WRB_TRIM(wrb, nacked); WRB_SEQNO(wrb) = ackno; WRB_SENT(wrb) -= nacked; nllvdbg("ACK: wrb=%p seqno=%u pktlen=%u sent=%u\n", wrb, WRB_SEQNO(wrb), WRB_PKTLEN(wrb), WRB_SENT(wrb)); } } /* Check for a loss of connection */ else if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0) { nllvdbg("Lost connection: %04x\n", flags); /* Report not connected */ net_lostconnection(psock, flags); /* Free write buffers and terminate polling */ psock_lost_connection(psock, conn); return flags; } /* Check if we are being asked to retransmit data */ else if ((flags & TCP_REXMIT) != 0) { FAR struct tcp_wrbuffer_s *wrb; FAR sq_entry_t *entry; nllvdbg("REXMIT: %04x\n", flags); /* If there is a partially sent write buffer at the head of the * write_q? Has anything been sent from that write buffer? */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); nllvdbg("REXMIT: wrb=%p sent=%u\n", wrb, wrb ? WRB_SENT(wrb) : 0); if (wrb != NULL && WRB_SENT(wrb) > 0) { FAR struct tcp_wrbuffer_s *tmp; uint16_t sent; /* Yes.. Reset the number of bytes sent sent from the write buffer */ sent = WRB_SENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; } else { conn->unacked = 0; } if (conn->sent > sent) { conn->sent -= sent; } else { conn->sent = 0; } WRB_SENT(wrb) = 0; nllvdbg("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", wrb, WRB_SENT(wrb), conn->unacked, conn->sent); /* Increment the retransmit count on this write buffer. */ if (++WRB_NRTX(wrb) >= TCP_MAXRTX) { nlldbg("Expiring wrb=%p nrtx=%u\n", wrb, WRB_NRTX(wrb)); /* The maximum retry count as been exhausted. Remove the write * buffer at the head of the queue. */ tmp = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&conn->write_q); DEBUGASSERT(tmp == wrb); UNUSED(tmp); /* And return the write buffer to the free list */ tcp_wrbuffer_release(wrb); /* NOTE expired is different from un-ACKed, it is designed to * represent the number of segments that have been sent, * retransmitted, and un-ACKed, if expired is not zero, the * connection will be closed. * * field expired can only be updated at TCP_ESTABLISHED state */ conn->expired++; } } /* Move all segments that have been sent but not ACKed to the write * queue again note, the un-ACKed segments are put at the head of the * write_q so they can be resent as soon as possible. */ while ((entry = sq_remlast(&conn->unacked_q)) != NULL) { wrb = (FAR struct tcp_wrbuffer_s*)entry; uint16_t sent; /* Reset the number of bytes sent sent from the write buffer */ sent = WRB_SENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; } else { conn->unacked = 0; } if (conn->sent > sent) { conn->sent -= sent; } else { conn->sent = 0; } WRB_SENT(wrb) = 0; nllvdbg("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", wrb, WRB_SENT(wrb), conn->unacked, conn->sent); /* Free any write buffers that have exceed the retry count */ if (++WRB_NRTX(wrb) >= TCP_MAXRTX) { nlldbg("Expiring wrb=%p nrtx=%u\n", wrb, WRB_NRTX(wrb)); /* Return the write buffer to the free list */ tcp_wrbuffer_release(wrb); /* NOTE expired is different from un-ACKed, it is designed to * represent the number of segments that have been sent, * retransmitted, and un-ACKed, if expired is not zero, the * connection will be closed. * * field expired can only be updated at TCP_ESTABLISHED state */ conn->expired++; continue; } else { /* Insert the write buffer into the write_q (in sequence * number order). The retransmission will occur below * when the write buffer with the lowest sequenc number * is pulled from the write_q again. */ nllvdbg("REXMIT: Moving wrb=%p nrtx=%u\n", wrb, WRB_NRTX(wrb)); psock_insert_segment(wrb, &conn->write_q); } } } /* Check if the outgoing packet is available (it may have been claimed * by a sendto interrupt serving a different thread). */ if (dev->d_sndlen > 0) { /* Another thread has beat us sending data, wait for the next poll */ return flags; } /* We get here if (1) not all of the data has been ACKed, (2) we have been * asked to retransmit data, (3) the connection is still healthy, and (4) * the outgoing packet is available for our use. In this case, we are * now free to send more data to receiver -- UNLESS the buffer contains * unprocessed incoming data. In that event, we will have to wait for the * next polling cycle. */ if ((conn->tcpstateflags & TCP_ESTABLISHED) && (flags & (TCP_POLL | TCP_REXMIT)) && !(sq_empty(&conn->write_q))) { /* Check if the destination IP address is in the ARP table. If not, * then the send won't actually make it out... it will be replaced with * an ARP request. * * NOTE 1: This could be an expensive check if there are a lot of * entries in the ARP table. * * NOTE 2: If we are actually harvesting IP addresses on incoming IP * packets, then this check should not be necessary; the MAC mapping * should already be in the ARP table in many cases. * * NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP * address mapping is already in the ARP table. */ #if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \ !defined(CONFIG_NET_ARP_SEND) if (arp_find(conn->ripaddr) != NULL) #endif { FAR struct tcp_wrbuffer_s *wrb; size_t sndlen; /* Peek at the head of the write queue (but don't remove anything * from the write queue yet). We know from the above test that * the write_q is not empty. */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); DEBUGASSERT(wrb); /* Get the amount of data that we can send in the next packet. * We will send either the remaining data in the buffer I/O * buffer chain, or as much as will fit given the MSS and current * window size. */ sndlen = WRB_PKTLEN(wrb) - WRB_SENT(wrb); if (sndlen > tcp_mss(conn)) { sndlen = tcp_mss(conn); } if (sndlen > conn->winsize) { sndlen = conn->winsize; } nllvdbg("SEND: wrb=%p pktlen=%u sent=%u sndlen=%u\n", wrb, WRB_PKTLEN(wrb), WRB_SENT(wrb), sndlen); /* Set the sequence number for this segment. If we are * retransmitting, then the sequence number will already * be set for this write buffer. */ if (WRB_SEQNO(wrb) == (unsigned)-1) { WRB_SEQNO(wrb) = conn->isn + conn->sent; } /* The TCP stack updates sndseq on receipt of ACK *before* * this function is called. In that case sndseq will point * to the next unacknowledged byte (which might have already * been sent). We will overwrite the value of sndseq here * before the packet is sent. */ tcp_setsequence(conn->sndseq, WRB_SEQNO(wrb) + WRB_SENT(wrb)); /* Then set-up to send that amount of data with the offset * corresponding to the amount of data already sent. (this * won't actually happen until the polling cycle completes). */ devif_iob_send(dev, WRB_IOB(wrb), sndlen, WRB_SENT(wrb)); /* Remember how much data we send out now so that we know * when everything has been acknowledged. Just increment * the amount of data sent. This will be needed in sequence * number calculations. */ conn->unacked += sndlen; conn->sent += sndlen; nllvdbg("SEND: wrb=%p nrtx=%u unacked=%u sent=%u\n", wrb, WRB_NRTX(wrb), conn->unacked, conn->sent); /* Increment the count of bytes sent from this write buffer */ WRB_SENT(wrb) += sndlen; nllvdbg("SEND: wrb=%p sent=%u pktlen=%u\n", wrb, WRB_SENT(wrb), WRB_PKTLEN(wrb)); /* Remove the write buffer from the write queue if the * last of the data has been sent from the buffer. */ DEBUGASSERT(WRB_SENT(wrb) <= WRB_PKTLEN(wrb)); if (WRB_SENT(wrb) >= WRB_PKTLEN(wrb)) { FAR struct tcp_wrbuffer_s *tmp; nllvdbg("SEND: wrb=%p Move to unacked_q\n", wrb); tmp = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&conn->write_q); DEBUGASSERT(tmp == wrb); UNUSED(tmp); /* Put the I/O buffer chain in the un-acked queue; the * segment is waiting for ACK again */ psock_insert_segment(wrb, &conn->unacked_q); } /* Only one data can be sent by low level driver at once, * tell the caller stop polling the other connection. */ flags &= ~TCP_POLL; } } /* Continue waiting */ return flags; }
SQInteger AIInfo::AddSetting(HSQUIRRELVM vm) { AIConfigItem config; memset(&config, 0, sizeof(config)); config.max_value = 1; config.step_size = 1; uint items = 0; /* Read the table, and find all properties we care about */ sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, -2))) { const SQChar *sqkey; if (SQ_FAILED(sq_getstring(vm, -2, &sqkey))) return SQ_ERROR; const char *key = SQ2OTTD(sqkey); if (strcmp(key, "name") == 0) { const SQChar *sqvalue; if (SQ_FAILED(sq_getstring(vm, -1, &sqvalue))) return SQ_ERROR; char *name = strdup(SQ2OTTD(sqvalue)); char *s; /* Don't allow '=' and ',' in configure setting names, as we need those * 2 chars to nicely store the settings as a string. */ while ((s = strchr(name, '=')) != NULL) *s = '_'; while ((s = strchr(name, ',')) != NULL) *s = '_'; config.name = name; items |= 0x001; } else if (strcmp(key, "description") == 0) { const SQChar *sqdescription; if (SQ_FAILED(sq_getstring(vm, -1, &sqdescription))) return SQ_ERROR; config.description = strdup(SQ2OTTD(sqdescription)); items |= 0x002; } else if (strcmp(key, "min_value") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.min_value = res; items |= 0x004; } else if (strcmp(key, "max_value") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.max_value = res; items |= 0x008; } else if (strcmp(key, "easy_value") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.easy_value = res; items |= 0x010; } else if (strcmp(key, "medium_value") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.medium_value = res; items |= 0x020; } else if (strcmp(key, "hard_value") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.hard_value = res; items |= 0x040; } else if (strcmp(key, "random_deviation") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.random_deviation = res; items |= 0x200; } else if (strcmp(key, "custom_value") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.custom_value = res; items |= 0x080; } else if (strcmp(key, "step_size") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.step_size = res; } else if (strcmp(key, "flags") == 0) { SQInteger res; if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR; config.flags = (AIConfigFlags)res; items |= 0x100; } else { char error[1024]; snprintf(error, sizeof(error), "unknown setting property '%s'", key); this->engine->ThrowError(error); return SQ_ERROR; } sq_pop(vm, 2); } sq_pop(vm, 1); /* Don't allow both random_deviation and AICONFIG_RANDOM to * be set for the same config item. */ if ((items & 0x200) != 0 && (config.flags & AICONFIG_RANDOM) != 0) { char error[1024]; snprintf(error, sizeof(error), "Setting both random_deviation and AICONFIG_RANDOM is not allowed"); this->engine->ThrowError(error); return SQ_ERROR; } /* Reset the bit for random_deviation as it's optional. */ items &= ~0x200; /* Make sure all properties are defined */ uint mask = (config.flags & AICONFIG_BOOLEAN) ? 0x1F3 : 0x1FF; if (items != mask) { char error[1024]; snprintf(error, sizeof(error), "please define all properties of a setting (min/max not allowed for booleans)"); this->engine->ThrowError(error); return SQ_ERROR; } this->config_list.push_back(config); return 0; }
bool CSquirrelArgument::pushFromStack(SQVM * pVM, int idx) { reset(); SQObjectPtr obj = stack_get(pVM, idx); switch(obj._type) { case OT_NULL: // Nothing needed break; case OT_INTEGER: data.i = obj._unVal.nInteger; break; case OT_BOOL: data.b = (obj._unVal.nInteger != 0); break; case OT_FLOAT: data.f = obj._unVal.fFloat; break; case OT_STRING: data.str = new String(obj._unVal.pString->_val); break; case OT_TABLE: { CSquirrelArguments * pArguments = new CSquirrelArguments(); sq_push(pVM, idx); sq_pushnull(pVM); while(SQ_SUCCEEDED(sq_next(pVM, -2))) { if(!pArguments->pushFromStack(pVM, -2) || !pArguments->pushFromStack(pVM, -1)) { sq_pop(pVM, 4); delete pArguments; return false; } sq_pop(pVM, 2); } sq_pop(pVM, 2); data.pArray = pArguments; } break; case OT_ARRAY: { CSquirrelArguments * pArguments = new CSquirrelArguments(); sq_push(pVM, idx); sq_pushnull(pVM); while(SQ_SUCCEEDED(sq_next(pVM, -2))) { if(!pArguments->pushFromStack(pVM, -1)) { sq_pop(pVM, 4); delete pArguments; return false; } sq_pop(pVM, 2); } sq_pop(pVM, 2); data.pArray = pArguments; } break; case OT_CLOSURE: case OT_NATIVECLOSURE: data.sqObject = SQObject(obj); break; case OT_INSTANCE: data.pInstance = obj._unVal.pInstance; break; default: return false; break; } type = obj._type; return true; }