static void listener_next_job_handler (BListener *o) { DebugObject_Access(&o->d_obj); ASSERT(!o->busy) // free ready socket if (o->ready) { BLog(BLOG_ERROR, "discarding connection"); // close new socket if (closesocket(o->newsock) == SOCKET_ERROR) { BLog(BLOG_ERROR, "closesocket failed"); } // set not ready o->ready = 0; } // create new socket if ((o->newsock = WSASocket(o->sys_family, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { BLog(BLOG_ERROR, "WSASocket failed"); goto fail0; } // start accept operation while (1) { memset(&o->olap.olap, 0, sizeof(o->olap.olap)); DWORD bytes; BOOL res = o->fnAcceptEx(o->sock, o->newsock, o->addrbuf, 0, sizeof(struct BListener_addrbuf_stub), sizeof(struct BListener_addrbuf_stub), &bytes, &o->olap.olap); if (res == FALSE && WSAGetLastError() != ERROR_IO_PENDING) { BLog(BLOG_ERROR, "AcceptEx failed"); continue; } break; } // set busy o->busy = 1; return; fail0: return; }
static void input_handler_send (PacketPassFifoQueueFlow *o, uint8_t *data, int data_len) { PacketPassFifoQueue *queue = o->queue; DebugObject_Access(&o->d_obj); ASSERT(!o->is_waiting) ASSERT(o != queue->sending_flow) ASSERT(!queue->freeing) // queue flow o->waiting_data = data; o->waiting_len = data_len; LinkedList1_Append(&queue->waiting_flows_list, &o->waiting_flows_list_node); o->is_waiting = 1; // schedule if (!queue->sending_flow && !BPending_IsSet(&queue->schedule_job)) { schedule(queue); } }
int BufferWriter_StartPacket (BufferWriter *o, uint8_t **buf) { ASSERT(!o->d_writing) DebugObject_Access(&o->d_obj); if (!o->out_have) { return 0; } if (buf) { *buf = o->out; } #ifndef NDEBUG o->d_writing = 1; #endif return 1; }
void OTPGenerator_SetSeed (OTPGenerator *g, uint8_t *key, uint8_t *iv) { DebugObject_Access(&g->d_obj); // free existing work if (g->tw_have) { BThreadWork_Free(&g->tw); } // copy key and IV memcpy(g->tw_key, key, BEncryption_cipher_key_size(g->cipher)); memcpy(g->tw_iv, iv, BEncryption_cipher_block_size(g->cipher)); // start work BThreadWork_Init(&g->tw, g->twd, (BThreadWork_handler_done)work_done_handler, g, (BThreadWork_work_func)work_func, g); // set have work g->tw_have = 1; }
void BPendingGroup_ExecuteJob (BPendingGroup *g) { ASSERT(!LinkedList1_IsEmpty(&g->jobs)) DebugObject_Access(&g->d_obj); // get a job LinkedList1Node *node = LinkedList1_GetLast(&g->jobs); BPending *p = UPPER_OBJECT(node, BPending, pending_node); ASSERT(p->pending) // remove from jobs list LinkedList1_Remove(&g->jobs, &p->pending_node); // set not pending p->pending = 0; // execute job p->handler(p->user); return; }
void PacketPassFifoQueueFlow_Init (PacketPassFifoQueueFlow *o, PacketPassFifoQueue *queue) { DebugObject_Access(&queue->d_obj); ASSERT(!queue->freeing) // init arguments o->queue = queue; // init input PacketPassInterface_Init(&o->input, PacketPassInterface_GetMTU(queue->output), (PacketPassInterface_handler_send)input_handler_send, o, queue->pg); // set not waiting o->is_waiting = 0; // set no busy handler o->handler_busy = NULL; DebugCounter_Increment(&queue->d_flows_ctr); DebugObject_Init(&o->d_obj); }
int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp) { DebugObject_Access(&mc->d_obj); // try tables in reverse order for (int i = 1; i <= mc->tables_used; i++) { int table_index = bmodadd_int(mc->next_table, mc->num_tables - i, mc->num_tables); if (table_index == mc->next_table && mc->tw_have) { // ignore table that is being generated continue; } struct OTPChecker_table *table = &mc->tables[table_index]; if (table->id == seed_id) { return OTPChecker_Table_CheckOTP(mc, table, otp); } } return 0; }
void output_handler_done (PacketBuffer *buf) { DebugObject_Access(&buf->d_obj); // remember if buffer is full int was_full = (buf->buf.input_avail < buf->input_mtu); // remove packet from buffer ChunkBuffer2_ConsumePacket(&buf->buf); // if buffer was full and there is space, schedule receive if (was_full && buf->buf.input_avail >= buf->input_mtu) { PacketRecvInterface_Receiver_Recv(buf->input, buf->buf.input_dest); } // if there is more data, schedule send if (buf->buf.output_avail >= 0) { PacketPassInterface_Sender_Send(buf->output, buf->buf.output_dest, buf->buf.output_avail); } }
static void connector_olap_handler (BConnector *o, int event, DWORD bytes) { DebugObject_Access(&o->d_obj); ASSERT(o->sock != INVALID_SOCKET) ASSERT(o->busy) ASSERT(!o->ready) ASSERT(event == BREACTOR_IOCP_EVENT_SUCCEEDED || event == BREACTOR_IOCP_EVENT_FAILED) // set not busy o->busy = 0; if (event == BREACTOR_IOCP_EVENT_FAILED) { BLog(BLOG_ERROR, "connection failed"); } else { // set ready o->ready = 1; } // call handler o->handler(o->user, !o->ready); return; }
void input_handler_done (PacketBuffer *buf, int in_len) { ASSERT(in_len >= 0) ASSERT(in_len <= buf->input_mtu) DebugObject_Access(&buf->d_obj); // remember if buffer is empty int was_empty = (buf->buf.output_avail < 0); // submit packet to buffer ChunkBuffer2_SubmitPacket(&buf->buf, in_len); // if there is space, schedule receive if (buf->buf.input_avail >= buf->input_mtu) { PacketRecvInterface_Receiver_Recv(buf->input, buf->buf.input_dest); } // if buffer was empty, schedule send if (was_empty) { PacketPassInterface_Sender_Send(buf->output, buf->buf.output_dest, buf->buf.output_avail); } }
static void work_done_handler (OTPChecker *mc) { ASSERT(mc->tw_have) DebugObject_Access(&mc->d_obj); // free work BThreadWork_Free(&mc->tw); mc->tw_have = 0; // update next table number mc->next_table = bmodadd_int(mc->next_table, 1, mc->num_tables); // update number of used tables if not all are used yet if (mc->tables_used < mc->num_tables) { mc->tables_used++; } // call handler if (mc->handler) { mc->handler(mc->user); return; } }
void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv) { ASSERT(mc->next_table >= 0) ASSERT(mc->next_table < mc->num_tables) DebugObject_Access(&mc->d_obj); // free existing work if (mc->tw_have) { BThreadWork_Free(&mc->tw); } // set table's seed ID mc->tables[mc->next_table].id = seed_id; // copy key and IV memcpy(mc->tw_key, key, BEncryption_cipher_key_size(mc->cipher)); memcpy(mc->tw_iv, iv, BEncryption_cipher_block_size(mc->cipher)); // start work BThreadWork_Init(&mc->tw, mc->twd, (BThreadWork_handler_done)work_done_handler, mc, (BThreadWork_work_func)work_func, mc); // set have work mc->tw_have = 1; }
static void receiver_recv_handler_send (DPReceiveReceiver *o, uint8_t *packet, int packet_len) { DebugObject_Access(&o->d_obj); DPReceivePeer *peer = o->peer; DPReceiveDevice *device = peer->device; ASSERT(packet_len >= 0) ASSERT(packet_len <= device->packet_mtu) uint8_t *data = packet; int data_len = packet_len; int local = 0; DPReceivePeer *src_peer; DPReceivePeer *relay_dest_peer = NULL; // check header if (data_len < sizeof(struct dataproto_header)) { BLog(BLOG_WARNING, "no dataproto header"); goto out; } struct dataproto_header header; memcpy(&header, data, sizeof(header)); data += sizeof(header); data_len -= sizeof(header); uint8_t flags = ltoh8(header.flags); peerid_t from_id = ltoh16(header.from_id); int num_ids = ltoh16(header.num_peer_ids); // check destination ID if (!(num_ids == 0 || num_ids == 1)) { BLog(BLOG_WARNING, "wrong number of destinations"); goto out; } peerid_t to_id = 0; // to remove warning if (num_ids == 1) { if (data_len < sizeof(struct dataproto_peer_id)) { BLog(BLOG_WARNING, "missing destination"); goto out; } struct dataproto_peer_id id; memcpy(&id, data, sizeof(id)); to_id = ltoh16(id.id); data += sizeof(id); data_len -= sizeof(id); } // check remaining data if (data_len > device->device_mtu) { BLog(BLOG_WARNING, "frame too large"); goto out; } // inform sink of received packet if (peer->dp_sink) { DataProtoSink_Received(peer->dp_sink, !!(flags & DATAPROTO_FLAGS_RECEIVING_KEEPALIVES)); } if (num_ids == 1) { // find source peer if (!(src_peer = find_peer(device, from_id))) { BLog(BLOG_INFO, "source peer %d not known", (int)from_id); goto out; } // is frame for device or another peer? if (device->have_peer_id && to_id == device->peer_id) { // let the frame decider analyze the frame FrameDeciderPeer_Analyze(src_peer->decider_peer, data, data_len); // pass frame to device local = 1; } else { // check if relaying is allowed if (!peer->is_relay_client) { BLog(BLOG_WARNING, "relaying not allowed"); goto out; } // provided source ID must be the peer sending the frame if (src_peer != peer) { BLog(BLOG_WARNING, "relay source must be the sending peer"); goto out; } // find destination peer DPReceivePeer *dest_peer = find_peer(device, to_id); if (!dest_peer) { BLog(BLOG_INFO, "relay destination peer not known"); goto out; } // destination cannot be source if (dest_peer == src_peer) { BLog(BLOG_WARNING, "relay destination cannot be the source"); goto out; } relay_dest_peer = dest_peer; } } out: // accept packet PacketPassInterface_Done(&o->recv_if); // pass packet to device if (local) { o->device->output_func(o->device->output_func_user, data, data_len); } // relay frame if (relay_dest_peer) { DPRelayRouter_SubmitFrame(&device->relay_router, &src_peer->relay_source, &relay_dest_peer->relay_sink, data, data_len, device->relay_flow_buffer_size, device->relay_flow_inactivity_time); } }
PacketPassInterface * DPReceiveReceiver_GetInput (DPReceiveReceiver *o) { DebugObject_Access(&o->d_obj); return &o->recv_if; }
PacketPassInterface * PacketPassFifoQueueFlow_GetInput (PacketPassFifoQueueFlow *o) { DebugObject_Access(&o->d_obj); return &o->input; }
void NCDUdevMonitor_AssertReady (NCDUdevMonitor *o) { DebugObject_Access(&o->d_obj); DebugError_AssertNoError(&o->d_err); NCDUdevMonitorParser_AssertReady(&o->parser); }
void send_handler_done (BSocksClient *o) { DebugObject_Access(&o->d_obj); ASSERT(o->buffer) switch (o->state) { case STATE_SENDING_HELLO: { BLog(BLOG_DEBUG, "sent hello"); // allocate buffer for receiving hello bsize_t size = bsize_fromsize(sizeof(struct socks_server_hello)); if (!reserve_buffer(o, size)) { goto fail; } // receive hello start_receive(o, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENT_HELLO; } break; case STATE_SENDING_REQUEST: { BLog(BLOG_DEBUG, "sent request"); // allocate buffer for receiving reply bsize_t size = bsize_add( bsize_fromsize(sizeof(struct socks_reply_header)), bsize_max(bsize_fromsize(sizeof(struct socks_addr_ipv4)), bsize_fromsize(sizeof(struct socks_addr_ipv6))) ); if (!reserve_buffer(o, size)) { goto fail; } // receive reply header start_receive(o, (uint8_t *)o->buffer, sizeof(struct socks_reply_header)); // set state o->state = STATE_SENT_REQUEST; } break; case STATE_SENDING_PASSWORD: { BLog(BLOG_DEBUG, "send password"); // allocate buffer for receiving reply bsize_t size = bsize_fromsize(2); if (!reserve_buffer(o, size)) { goto fail; } // receive reply header start_receive(o, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENT_PASSWORD; } break; default: ASSERT(0); } return; fail: report_error(o, BSOCKSCLIENT_EVENT_ERROR); }
void connector_handler (BSocksClient* o, int is_error) { DebugObject_Access(&o->d_obj); ASSERT(o->state == STATE_CONNECTING) // check connection result if (is_error) { // PSIPHON // BLog(BLOG_ERROR, "connection failed"); BLog(BLOG_WARNING, "connection failed"); goto fail0; } // init connection if (!BConnection_Init(&o->con, BConnection_source_connector(&o->connector), o->reactor, o, (BConnection_handler)connection_handler)) { BLog(BLOG_ERROR, "BConnection_Init failed"); goto fail0; } BLog(BLOG_DEBUG, "connected"); // init control I/O init_control_io(o); // check number of methods if (o->num_auth_info == 0 || o->num_auth_info > 255) { BLog(BLOG_ERROR, "invalid number of authentication methods"); goto fail1; } // allocate buffer for sending hello bsize_t size = bsize_add( bsize_fromsize(sizeof(struct socks_client_hello_header)), bsize_mul( bsize_fromsize(o->num_auth_info), bsize_fromsize(sizeof(struct socks_client_hello_method)) ) ); if (!reserve_buffer(o, size)) { goto fail1; } // write hello header struct socks_client_hello_header header; header.ver = hton8(SOCKS_VERSION); header.nmethods = hton8(o->num_auth_info); memcpy(o->buffer, &header, sizeof(header)); // write hello methods for (size_t i = 0; i < o->num_auth_info; i++) { struct socks_client_hello_method method; method.method = hton8(o->auth_info[i].auth_type); memcpy(o->buffer + sizeof(header) + i * sizeof(method), &method, sizeof(method)); } // send PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENDING_HELLO; return; fail1: free_control_io(o); BConnection_Free(&o->con); fail0: report_error(o, BSOCKSCLIENT_EVENT_ERROR); return; }
static void output_handler_done (SinglePacketBuffer *o) { DebugObject_Access(&o->d_obj); PacketRecvInterface_Receiver_Recv(o->input, o->buf); }
int BPending_IsSet (BPending *o) { DebugObject_Access(&o->d_obj); return o->pending; }
BufferWriter * PacketProtoFlow_GetInput (PacketProtoFlow *o) { DebugObject_Access(&o->d_obj); return &o->ainput; }
int OTPGenerator_GetPosition (OTPGenerator *g) { DebugObject_Access(&g->d_obj); return g->position; }
static void recv_if_handler_done (BArpProbe *o, int data_len) { DebugObject_Access(&o->d_obj); ASSERT(data_len >= 0) ASSERT(data_len <= sizeof(struct arp_packet)) // receive next packet PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)&o->recv_packet); if (data_len != sizeof(struct arp_packet)) { BLog(BLOG_WARNING, "receive: wrong size"); return; } struct arp_packet *arp = &o->recv_packet; if (ntoh16(arp->hardware_type) != ARP_HARDWARE_TYPE_ETHERNET) { BLog(BLOG_WARNING, "receive: wrong hardware type"); return; } if (ntoh16(arp->protocol_type) != ETHERTYPE_IPV4) { BLog(BLOG_WARNING, "receive: wrong protocol type"); return; } if (ntoh8(arp->hardware_size) != 6) { BLog(BLOG_WARNING, "receive: wrong hardware size"); return; } if (ntoh8(arp->protocol_size) != 4) { BLog(BLOG_WARNING, "receive: wrong protocol size"); return; } if (ntoh16(arp->opcode) != ARP_OPCODE_REPLY) { return; } if (arp->sender_ip != o->addr) { return; } int old_state = o->state; // set minus one missed o->num_missed = -1; // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_WAITSEND); // set state exist o->state = STATE_EXIST; // report exist if needed if (old_state == STATE_INITIAL || old_state == STATE_NOEXIST) { o->handler(o->user, BARPPROBE_EVENT_EXIST); return; } }
PacketRecvInterface * BufferWriter_GetOutput (BufferWriter *o) { DebugObject_Access(&o->d_obj); return &o->recv_interface; }
void connector_handler (ServerConnection *o, int is_error) { DebugObject_Access(&o->d_obj); ASSERT(o->state == STATE_CONNECTING) ASSERT(!o->buffers_released) // check connection attempt result if (is_error) { BLog(BLOG_ERROR, "connection failed"); goto fail0; } BLog(BLOG_NOTICE, "connected"); // init connection if (!BConnection_Init(&o->con, BConnection_source_connector(&o->connector), o->reactor, o, (BConnection_handler)connection_handler)) { BLog(BLOG_ERROR, "BConnection_Init failed"); goto fail0; } // init connection interfaces BConnection_SendAsync_Init(&o->con); BConnection_RecvAsync_Init(&o->con); StreamPassInterface *send_iface = BConnection_SendAsync_GetIf(&o->con); StreamRecvInterface *recv_iface = BConnection_RecvAsync_GetIf(&o->con); if (o->have_ssl) { // create bottom NSPR file descriptor if (!BSSLConnection_MakeBackend(&o->bottom_prfd, send_iface, recv_iface, o->twd, o->ssl_flags)) { BLog(BLOG_ERROR, "BSSLConnection_MakeBackend failed"); goto fail0a; } // create SSL file descriptor from the bottom NSPR file descriptor if (!(o->ssl_prfd = SSL_ImportFD(NULL, &o->bottom_prfd))) { BLog(BLOG_ERROR, "SSL_ImportFD failed"); ASSERT_FORCE(PR_Close(&o->bottom_prfd) == PR_SUCCESS) goto fail0a; } // set client mode if (SSL_ResetHandshake(o->ssl_prfd, PR_FALSE) != SECSuccess) { BLog(BLOG_ERROR, "SSL_ResetHandshake failed"); goto fail1; } // set server name if (SSL_SetURL(o->ssl_prfd, o->server_name) != SECSuccess) { BLog(BLOG_ERROR, "SSL_SetURL failed"); goto fail1; } // set client certificate callback if (SSL_GetClientAuthDataHook(o->ssl_prfd, (SSLGetClientAuthData)client_auth_data_callback, o) != SECSuccess) { BLog(BLOG_ERROR, "SSL_GetClientAuthDataHook failed"); goto fail1; } // init BSSLConnection BSSLConnection_Init(&o->sslcon, o->ssl_prfd, 0, BReactor_PendingGroup(o->reactor), o, (BSSLConnection_handler)sslcon_handler); send_iface = BSSLConnection_GetSendIf(&o->sslcon); recv_iface = BSSLConnection_GetRecvIf(&o->sslcon); }
PacketRecvInterface * SCOutmsgEncoder_GetOutput (SCOutmsgEncoder *o) { DebugObject_Access(&o->d_obj); return &o->output; }
void recv_handler_done (BSocksClient *o, int data_len) { ASSERT(data_len >= 0) ASSERT(data_len <= o->control.recv_total - o->control.recv_len) DebugObject_Access(&o->d_obj); o->control.recv_len += data_len; if (o->control.recv_len < o->control.recv_total) { do_receive(o); return; } switch (o->state) { case STATE_SENT_HELLO: { BLog(BLOG_DEBUG, "received hello"); struct socks_server_hello imsg; memcpy(&imsg, o->buffer, sizeof(imsg)); if (ntoh8(imsg.ver) != SOCKS_VERSION) { BLog(BLOG_NOTICE, "wrong version"); goto fail; } size_t auth_index; for (auth_index = 0; auth_index < o->num_auth_info; auth_index++) { if (o->auth_info[auth_index].auth_type == ntoh8(imsg.method)) { break; } } if (auth_index == o->num_auth_info) { BLog(BLOG_NOTICE, "server didn't accept any authentication method"); goto fail; } const struct BSocksClient_auth_info *ai = &o->auth_info[auth_index]; switch (ai->auth_type) { case SOCKS_METHOD_NO_AUTHENTICATION_REQUIRED: { BLog(BLOG_DEBUG, "no authentication"); auth_finished(o); } break; case SOCKS_METHOD_USERNAME_PASSWORD: { BLog(BLOG_DEBUG, "password authentication"); if (ai->password.username_len == 0 || ai->password.username_len > 255 || ai->password.password_len == 0 || ai->password.password_len > 255 ) { BLog(BLOG_NOTICE, "invalid username/password length"); goto fail; } // allocate password packet bsize_t size = bsize_fromsize(1 + 1 + ai->password.username_len + 1 + ai->password.password_len); if (!reserve_buffer(o, size)) { goto fail; } // write password packet char *ptr = o->buffer; *ptr++ = 1; *ptr++ = ai->password.username_len; memcpy(ptr, ai->password.username, ai->password.username_len); ptr += ai->password.username_len; *ptr++ = ai->password.password_len; memcpy(ptr, ai->password.password, ai->password.password_len); ptr += ai->password.password_len; // start sending PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENDING_PASSWORD; } break; default: ASSERT(0); } } break; case STATE_SENT_REQUEST: { BLog(BLOG_DEBUG, "received reply header"); struct socks_reply_header imsg; memcpy(&imsg, o->buffer, sizeof(imsg)); if (ntoh8(imsg.ver) != SOCKS_VERSION) { BLog(BLOG_NOTICE, "wrong version"); goto fail; } if (ntoh8(imsg.rep) != SOCKS_REP_SUCCEEDED) { BLog(BLOG_NOTICE, "reply not successful"); goto fail; } int addr_len; switch (ntoh8(imsg.atyp)) { case SOCKS_ATYP_IPV4: addr_len = sizeof(struct socks_addr_ipv4); break; case SOCKS_ATYP_IPV6: addr_len = sizeof(struct socks_addr_ipv6); break; default: BLog(BLOG_NOTICE, "reply has unknown address type"); goto fail; } // receive the rest of the reply start_receive(o, (uint8_t *)o->buffer + sizeof(imsg), addr_len); // set state o->state = STATE_RECEIVED_REPLY_HEADER; } break; case STATE_SENT_PASSWORD: { BLog(BLOG_DEBUG, "received password reply"); if (o->buffer[0] != 1) { BLog(BLOG_NOTICE, "password reply has unknown version"); goto fail; } if (o->buffer[1] != 0) { BLog(BLOG_NOTICE, "password reply is negative"); goto fail; } auth_finished(o); } break; case STATE_RECEIVED_REPLY_HEADER: { BLog(BLOG_DEBUG, "received reply rest"); // free buffer BFree(o->buffer); o->buffer = NULL; // free control I/O free_control_io(o); // init up I/O init_up_io(o); // set state o->state = STATE_UP; // call handler o->handler(o->user, BSOCKSCLIENT_EVENT_UP); return; } break; default: ASSERT(0); } return; fail: report_error(o, BSOCKSCLIENT_EVENT_ERROR); }
static void input_handler_done (SinglePacketBuffer *o, int in_len) { DebugObject_Access(&o->d_obj); PacketPassInterface_Sender_Send(o->output, o->buf, in_len); }
int BPendingGroup_HasJobs (BPendingGroup *g) { DebugObject_Access(&g->d_obj); return !LinkedList1_IsEmpty(&g->jobs); }
static void timer_handler (BArpProbe *o) { DebugObject_Access(&o->d_obj); // send request send_request(o); switch (o->state) { case STATE_INITIAL: { ASSERT(o->num_missed >= 0) ASSERT(o->num_missed < BARPPROBE_INITIAL_NUM_ATTEMPTS) // increment missed o->num_missed++; // all attempts failed? if (o->num_missed == BARPPROBE_INITIAL_NUM_ATTEMPTS) { // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV); // set state noexist o->state = STATE_NOEXIST; // report noexist o->handler(o->user, BARPPROBE_EVENT_NOEXIST); return; } // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_INITIAL_WAITRECV); } break; case STATE_NOEXIST: { // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV); } break; case STATE_EXIST: { ASSERT(o->num_missed >= -1) ASSERT(o->num_missed < BARPPROBE_EXIST_NUM_NOREPLY) // increment missed o->num_missed++; // all missed? if (o->num_missed == BARPPROBE_EXIST_NUM_NOREPLY) { // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_PANIC_WAITRECV); // set zero missed o->num_missed = 0; // set state panic o->state = STATE_EXIST_PANIC; return; } // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_WAITRECV); } break; case STATE_EXIST_PANIC: { ASSERT(o->num_missed >= 0) ASSERT(o->num_missed < BARPPROBE_EXIST_PANIC_NUM_NOREPLY) // increment missed o->num_missed++; // all missed? if (o->num_missed == BARPPROBE_EXIST_PANIC_NUM_NOREPLY) { // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV); // set state panic o->state = STATE_NOEXIST; // report noexist o->handler(o->user, BARPPROBE_EVENT_NOEXIST); return; } // set timer BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_PANIC_WAITRECV); } break; } }