int cell_main(int argc, char **argv) { struct disk_message *msg; int status; unsigned long disk_size, sector; msg = malloc(DISK_MESSAGE_SIZE); // Query the disk to get its size so we know how to do our // reads. msg->type = DISK_MSG_GET_SIZE; if ((status = channel_send(to_disk1, msg))) { printf("[cell1] Could not send disk message: %d\n", status); return 1; } else printf("[cell1] sent size request\n"); if ((status = channel_recv(from_disk1, msg))) { printf("[cell1] Could not get disk reply: %d\n", status); return 1; } if (msg->type != DISK_MSG_GET_SIZE) { printf("[cell1] Something bad happened; got non-size reply (type %d)\n", msg->type); return 1; } disk_size = msg->body.device_size; sector = 0; // Loop forever, reading sectors from disk one at a time and // sending them to the neighboring cell. When we reach the end of // the disk, start over. while (1) { msg->type = DISK_MSG_IO_REQUEST; msg->body.io_request.type = DISK_IO_REQUEST_READ; msg->body.io_request.num_sectors = 1; msg->body.io_request.start_sector = sector; if ((status = channel_send(to_disk1, msg))) { printf("[cell1] Could not send disk read for sector %ld: %d\n", sector, status); return 1; } if ((status = channel_recv(from_disk1, msg))) { printf("[cell1] Could not receive disk read result: %d\n", status); return 1; } if ((status = channel_send(middle, msg))) { printf("[cell1] Could not send disk data to cell 2: %d\n", status); return 1; } sector = (sector + 1) % (disk_size / SECTOR_SIZE); } return 0; }
int disk_client_write(struct disk_client *c, size_t num_sectors, unsigned long start_sector, unsigned char *buf, write_callback_t cb, error_callback_t err) { int slot_num, status; struct disk_client_slot *slot; if (channel_can_send(c->req_chan) && next_free_slot(c) >= 0) { slot_num = alloc_slot(c); slot = get_slot(c, slot_num); slot->cb.write = cb; slot->err = err; slot->msg.type = DISK_WRITE; slot->msg.start_sector = start_sector; slot->msg.num_sectors = num_sectors; slot->msg.handle = slot_num; memcpy(slot->msg.payload, buf, num_sectors * SECTOR_SIZE); status = channel_send(c->req_chan, &(slot->msg)); if (status == CHANNEL_OK) { return DISK_OK; } else { printf("Error in channel send (write): %d\n", status); return DISK_ERROR; } } return DISK_BUSY; }
int cell_main(int argc, char ** argv) { unsigned char msg; #if defined(SEL4_DEBUG_KERNEL) SET_MUSLC_SYSCALL_TABLE; platsupport_serial_setup_bootinfo_failsafe(); #endif // Read characater data from the input memory region, filter it (remove // vowels), and then emit it to the output memory region. // // This implementation uses a sequence number paired with each character to // facilitate data loss detection when scheduling interferes with memory // read/write operations in adjacent cells. while (1) { channel_recv(chan1, &msg); if (msg > 0) { if (msg == 'a' || msg == 'e' || msg == 'i' || msg == 'o' || msg == 'u') msg = '*'; channel_send(chan2, &msg); } } return 0; }
int disk_client_get_size(struct disk_client *c, size_callback_t cb, error_callback_t err) { int slot_num, status; struct disk_client_slot *slot; if (channel_can_send(c->req_chan) && next_free_slot(c) >= 0) { slot_num = alloc_slot(c); slot = get_slot(c, slot_num); slot->cb.size = cb; slot->err = err; slot->msg.type = DISK_SIZE; slot->msg.handle = slot_num; status = channel_send(c->req_chan, &(slot->msg)); if (status == CHANNEL_OK) { return DISK_OK; } else { printf("Error in channel send (size): %d\n", status); return DISK_ERROR; } } return DISK_BUSY; }
int disk_client_read(struct disk_client *c, size_t num_sectors, unsigned long start_sector, read_callback_t cb, error_callback_t err) { int slot_num, status; struct disk_client_slot *slot; if (channel_can_send(c->req_chan) && next_free_slot(c) >= 0) { slot_num = alloc_slot(c); slot = get_slot(c, slot_num); slot->cb.read = cb; slot->err = err; slot->msg.type = DISK_READ; slot->msg.start_sector = start_sector; slot->msg.num_sectors = num_sectors; slot->msg.handle = slot_num; status =channel_send(c->req_chan, &(slot->msg)); if (status == CHANNEL_OK) { return DISK_OK; } else { printf("Error in channel send (read): %d\n", status); return DISK_ERROR; } } return DISK_BUSY; }
/*===========================================================================* * rpc_query * *===========================================================================*/ int rpc_query(void) { /* Send a HGFS RPC query over the backdoor channel. Return OK upon success, or * a negative error code otherwise; EAGAIN is returned if shared folders are * disabled. In general, we make the assumption that the sender (= VMware) * speaks the protocol correctly. Hence, the callers of this function do not * check for lengths. */ int r, len, id, err; len = RPC_LEN; /* A more robust version of this call could reopen the channel and * retry the request upon low-level failure. */ r = channel_send(&rpc_chan, rpc_buf, len); if (r < 0) return r; r = channel_recv(&rpc_chan, rpc_buf, sizeof(rpc_buf)); if (r < 0) return r; if (r < 2 || (len > 2 && r < 10)) return EIO; RPC_RESET; if (RPC_NEXT8 != '1') return EAGAIN; if (RPC_NEXT8 != ' ') return EAGAIN; if (len <= 2) return OK; id = RPC_NEXT32; err = RPC_NEXT32; return error_convert(err); }
void rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer, uint32 length) { uint8 magic[4] = "rDCI"; STREAM s; #ifdef WITH_SCARD scard_lock(SCARD_LOCK_RDPDR); #endif s = channel_init(rdpdr_channel, 20 + length); out_uint8a(s, magic, 4); out_uint32_le(s, device); out_uint32_le(s, id); out_uint32_le(s, status); out_uint32_le(s, result); out_uint8p(s, buffer, length); s_mark_end(s); /* JIF */ #ifdef WITH_DEBUG_RDP5 printf("--> rdpdr_send_completion\n"); /* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */ #endif channel_send(s, rdpdr_channel); #ifdef WITH_SCARD scard_unlock(SCARD_LOCK_RDPDR); #endif }
static void rdpdr_send_available(RDPCLIENT * This) { uint8 magic[4] = "rDAD"; uint32 driverlen, printerlen, bloblen; int i; STREAM s; PRINTER *printerinfo; s = channel_init(This, This->rdpdr.channel, announcedata_size(This)); out_uint8a(s, magic, 4); out_uint32_le(s, This->num_devices); for (i = 0; i < This->num_devices; i++) { out_uint32_le(s, This->rdpdr_device[i].device_type); out_uint32_le(s, i); /* RDP Device ID */ /* Is it possible to use share names longer than 8 chars? /astrand */ out_uint8p(s, This->rdpdr_device[i].name, 8); switch (This->rdpdr_device[i].device_type) { case DEVICE_TYPE_PRINTER: printerinfo = (PRINTER *) This->rdpdr_device[i].pdevice_data; driverlen = 2 * strlen(printerinfo->driver) + 2; printerlen = 2 * strlen(printerinfo->printer) + 2; bloblen = printerinfo->bloblen; out_uint32_le(s, 24 + driverlen + printerlen + bloblen); /* length of extra info */ out_uint32_le(s, printerinfo->default_printer ? 2 : 0); out_uint8s(s, 8); /* unknown */ out_uint32_le(s, driverlen); out_uint32_le(s, printerlen); out_uint32_le(s, bloblen); rdp_out_unistr(This, s, printerinfo->driver, driverlen - 2); rdp_out_unistr(This, s, printerinfo->printer, printerlen - 2); out_uint8a(s, printerinfo->blob, bloblen); if (printerinfo->blob) xfree(printerinfo->blob); /* Blob is sent twice if reconnecting */ break; default: out_uint32(s, 0); } } #if 0 out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */ out_uint32_le(s, 0); out_uint8p(s, "SCARD", 5); out_uint8s(s, 3); out_uint32(s, 0); #endif s_mark_end(s); channel_send(This, s, This->rdpdr.channel); }
static void rdpusb_send(STREAM s) { #ifdef RDPUSB_DEBUG Log(("RDPUSB send:\n")); hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); #endif channel_send(s, rdpusb_channel); }
void rdpsnd_send(STREAM s) { #ifdef RDPSND_DEBUG printf("RDPSND send:\n"); hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); #endif channel_send(s, rdpsnd_channel); }
void finished_read(size_t num_sectors, unsigned long start_sector, unsigned char *buf) { struct disk_msg msg; printf("Got read response; sending to cell2\n"); msg.type = DISK_WRITE; msg.start_sector = start_sector; msg.num_sectors = num_sectors; memcpy(msg.payload, buf, num_sectors * SECTOR_SIZE); while (channel_send(forward, &msg) == CHANNEL_FULL) {} }
static void rdpdr_send_connect(RDPCLIENT * This) { uint8 magic[4] = "rDCC"; STREAM s; s = channel_init(This, This->rdpdr.channel, 12); out_uint8a(s, magic, 4); out_uint16_le(s, 1); /* unknown */ out_uint16_le(s, 5); out_uint32_be(s, 0x815ed39d); /* IP address (use 127.0.0.1) 0x815ed39d */ s_mark_end(s); channel_send(This, s, This->rdpdr.channel); }
static int write_block(FILE *p, blkif_sector_t sector, size_t amt) { static uint64_t next_reqid = 1; blkif_response_t *rsp; blkif_request_t *req; int notify, work_to_do; uint64_t reqid; RING_IDX i; /* wait until we can write something */ while(RING_FULL(&p->ring)) runtime_block(1); /* write out the request */ i = p->ring.req_prod_pvt++; req = RING_GET_REQUEST(&p->ring, i); memset(req, 0, sizeof(blkif_request_t)); req->operation = BLKIF_OP_WRITE; req->nr_segments = 1; req->handle = p->disk_handle; req->id = reqid = next_reqid++; req->sector_number = sector; req->seg[0].gref = p->block_grant; req->seg[0].first_sect = 0; req->seg[0].last_sect = (amt - 1) / 512; wmb(); RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&p->ring, notify); if(notify) channel_send(p->chan); /* wait for it to be satisfied */ do { while(!RING_HAS_UNCONSUMED_RESPONSES(&p->ring)) runtime_block(1); i = p->ring.rsp_cons++; rsp = RING_GET_RESPONSE(&p->ring, i); } while(rsp->id != reqid); /* was it successful? */ if(rsp->status != BLKIF_RSP_OKAY) { printf("PROFILING: Block write failed!\n"); return 0; } /* we do writes one at a time, synchronously, so work_to_do should always be false */ RING_FINAL_CHECK_FOR_RESPONSES(&p->ring, work_to_do); assert(!work_to_do); return 1; }
void * sendm(void * ptr) { channel_set chset; int err, nb = 0; msg_t tmp; tmp.pid = getpid(); sprintf(tmp.content," %ld @ %d !\n",pthread_self(),tmp.pid); chset.chan = chan_s; chset.events = CHANNEL_EVENT_WRITE|CHANNEL_EVENT_CLOSE; chset.revents = CHANNEL_EVENT_NOEVT; while(nb < MAX_MSG) { chset.revents = CHANNEL_EVENT_NOEVT; err = channel_select(&chset,1,CHANNEL_TIME_WAIT); if(err == -1) { perror("channel_select()"); } else if(err == 0) continue; if(CHAN_WRITE_EVT(chset.revents)) { err = channel_send(chan_s,&tmp); if(err == -1) { if(errno == EWOULDBLOCK) continue; perror("sendm channel_send()"); channel_close(chan_s); break; } nb++; } if(CHAN_CLOSE_EVT(chset.revents)) break; } pthread_exit(NULL); }
static void cliprdr_send_packet(uint16 type, uint16 status, uint8 * data, uint32 length) { STREAM s; DEBUG_CLIPBOARD(("CLIPRDR send: type=%d, status=%d, length=%d\n", type, status, length)); s = channel_init(cliprdr_channel, length + 12); out_uint16_le(s, type); out_uint16_le(s, status); out_uint32_le(s, length); out_uint8p(s, data, length); out_uint32(s, 0); /* pad? */ s_mark_end(s); channel_send(s, cliprdr_channel); }
/* Send data to channel */ static void lspci_send(const char *output) { STREAM s; size_t len; len = strlen(output); s = channel_init(lspci_channel, len); out_uint8p(s, output, len) s_mark_end(s); #if 0 printf("lspci send:\n"); hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); #endif channel_send(s, lspci_channel); }
static uint32_t xenstore_write(uint32_t type, uint32_t len, void *inbuf) { static uint32_t req_id = 1; struct xsd_sockmsg m; void *buffer, *cur; uint32_t prod; /* build out the header and adjust the final length */ m.type = type; m.req_id = req_id++; m.tx_id = 0; m.len = len; len += sizeof(struct xsd_sockmsg); /* wait until we can send out the data all at once */ while( (XENSTORE_RING_SIZE - (xsint->req_prod - xsint->req_cons)) < len ) runtime_block(1); assert( (xsint->req_prod + len - xsint->req_cons) < XENSTORE_RING_SIZE); /* Combine the data into one block */ cur = buffer = malloc(len); memcpy(buffer, &m, sizeof(struct xsd_sockmsg)); memcpy((void*)((uintptr_t)buffer + sizeof(struct xsd_sockmsg)), inbuf, m.len); /* dump it out to the ring */ prod = xsint->req_prod; while(len != 0) { uint32_t nextbit = min(len, XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod)); memcpy(xsint->req + MASK_XENSTORE_IDX(prod), cur, nextbit); prod += nextbit; cur = (void*)((uintptr_t)cur + nextbit); len -= nextbit; } /* notify the other size */ wmb(); xsint->req_prod = prod; channel_send(system_start_info->store_evtchn); /* free our buffer and return the request id */ free(buffer); return m.req_id; }
int mwChannel_sendEncrypted(struct mwChannel *chan, guint32 type, struct mwOpaque *data, gboolean encrypt) { struct mwMsgChannelSend *msg; g_return_val_if_fail(chan != NULL, -1); msg = (struct mwMsgChannelSend *) mwMessage_new(mwMessage_CHANNEL_SEND); msg->head.channel = chan->id; msg->type = type; mwOpaque_clone(&msg->data, data); if(encrypt && chan->cipher) { msg->head.options = mwMessageOption_ENCRYPT; mwCipherInstance_encrypt(chan->cipher, &msg->data); } return channel_send(chan, msg); }
int32_t _send( struct session * self, char * buf, uint32_t nbytes ) { int32_t rc = 0; if ( self->status&SESSION_EXITING ) { // 等待关闭的连接 return -1; } // 判断session是否繁忙 if ( !(self->status&SESSION_WRITING) && session_sendqueue_count(self) == 0 ) { // 直接发送 rc = channel_send( self, buf, nbytes ); if ( rc == nbytes ) { // 全部发送出去 return rc; } // 为什么发送错误没有直接终止会话呢? // 该接口有可能在ioservice_t中调用, 直接终止会话后, 会引发后续对会话的操作崩溃 } // 创建message, 添加到发送队列中 struct message * message = message_create(); if ( message == NULL ) { return -2; } message_add_buffer( message, buf+rc, nbytes-rc ); message_add_receiver( message, self->id ); QUEUE_PUSH(sendqueue)(&self->sendqueue, &message); session_add_event( self, EV_WRITE ); return rc; }
static void rdpdr_send_clientcapabilty(RDPCLIENT * This) { uint8 magic[4] = "rDPC"; STREAM s; s = channel_init(This, This->rdpdr.channel, 0x50); out_uint8a(s, magic, 4); out_uint32_le(s, 5); /* count */ out_uint16_le(s, 1); /* first */ out_uint16_le(s, 0x28); /* length */ out_uint32_le(s, 1); out_uint32_le(s, 2); out_uint16_le(s, 2); out_uint16_le(s, 5); out_uint16_le(s, 1); out_uint16_le(s, 5); out_uint16_le(s, 0xFFFF); out_uint16_le(s, 0); out_uint32_le(s, 0); out_uint32_le(s, 3); out_uint32_le(s, 0); out_uint32_le(s, 0); out_uint16_le(s, 2); /* second */ out_uint16_le(s, 8); /* length */ out_uint32_le(s, 1); out_uint16_le(s, 3); /* third */ out_uint16_le(s, 8); /* length */ out_uint32_le(s, 1); out_uint16_le(s, 4); /* fourth */ out_uint16_le(s, 8); /* length */ out_uint32_le(s, 1); out_uint16_le(s, 5); /* fifth */ out_uint16_le(s, 8); /* length */ out_uint32_le(s, 1); s_mark_end(s); channel_send(This, s, This->rdpdr.channel); }
static void rdpdr_send_completion(RDPCLIENT * This, uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer, uint32 length) { uint8 magic[4] = "rDCI"; STREAM s; s = channel_init(This, This->rdpdr.channel, 20 + length); out_uint8a(s, magic, 4); out_uint32_le(s, device); out_uint32_le(s, id); out_uint32_le(s, status); out_uint32_le(s, result); out_uint8p(s, buffer, length); s_mark_end(s); /* JIF */ #ifdef WITH_DEBUG_RDP5 printf("--> rdpdr_send_completion\n"); /* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */ #endif channel_send(This, s, This->rdpdr.channel); }
static void rdpdr_send_name(RDPCLIENT * This) { uint8 magic[4] = "rDNC"; STREAM s; uint32 hostlen; if (NULL == This->rdpdr_clientname) { This->rdpdr_clientname = This->hostname; } hostlen = (strlen(This->rdpdr_clientname) + 1) * 2; s = channel_init(This, This->rdpdr.channel, 16 + hostlen); out_uint8a(s, magic, 4); out_uint16_le(s, 0x63); /* unknown */ out_uint16_le(s, 0x72); out_uint32(s, 0); out_uint32_le(s, hostlen); rdp_out_unistr(This, s, This->rdpdr_clientname, hostlen - 2); s_mark_end(s); channel_send(This, s, This->rdpdr.channel); }
static void rdpdr_send_name(void) { uint8 magic[4] = "rDNC"; STREAM s; uint32 hostlen; if (NULL == g_rdpdr_clientname) { g_rdpdr_clientname = g_hostname; } hostlen = (strlen(g_rdpdr_clientname) + 1) * 2; s = channel_init(rdpdr_channel, 16 + hostlen); out_uint8a(s, magic, 4); out_uint16_le(s, 0x63); /* unknown */ out_uint16_le(s, 0x72); out_uint32(s, 0); out_uint32_le(s, hostlen); rdp_out_unistr(s, g_rdpdr_clientname, hostlen - 2); s_mark_end(s); channel_send(s, rdpdr_channel); }
void * sendm(void * ptr) { int err, nb = 0; msg_t tmp; tmp.pid = getpid(); sprintf(tmp.content," %ld @ %d !\n",pthread_self(),tmp.pid); while(nb < MAX_MSG) { err = channel_send(chan_s,&tmp); if(err == -1) { channel_close(chan_s); break; } nb++; } pthread_exit(NULL); }
static void rdpsnd_send(STREAM s) { channel_send(s, rdpsnd_channel); }
void producer(void *data) /*@ requires [1/2]info(data, ?channel_, ?space_, ?termScope, ?level_, ?creditObject_) &*& [1/2]info_nextToSend(data, 0) &*& debits(10, creditObject_) &*& channel_send_tokens(10, channel_, space_, termScope, level_, creditObject_, channel_inv(data)) &*& [_]obspace_credit_object_info(creditObject_, space_, level_) &*& obspace_joinee(space_) &*& [1/3]obligation_space(space_, termScope) &*& obspace_obligation_set(space_, n_times(nat_of_int(10), level_)); @*/ //@ ensures stop_perm(termScope); //@ terminates; { info info = data; channel channel = info->channel; //@ int space = info->space; //@ level level = info->level; //@ int creditObject = info->creditObject; for (unsigned int i = 0; i < 10; i = i + 1) /*@ invariant i <= 10 &*& debits(10 - i, creditObject_) &*& channel_send_tokens(10 - i, channel, space, termScope, level, creditObject, channel_inv(info)) &*& [_]obspace_credit_object_info(creditObject_, space_, level_) &*& i < 10 ? obspace_obligation_set(space, n_times(nat_of_int(10 - i), level)) &*& [1/2]info(info, _, space, termScope, _, _) &*& [1/3]obligation_space(space, termScope) &*& [1/2]info->nextToSend |-> i &*& obspace_joinee(space_) : stop_perm(termScope); @*/ //@ decreases 10 - (int)i; { //@ open channel_send_tokens(10 - i, channel, space, termScope, level, creditObject, channel_inv(info)); //@ level_all_above_or_eq_n_times(nat_of_int(10 - i), level); { /*@ predicate P() = [1/2]info->nextToSend |-> i &*& i == 9 ? [1/2]info(info, _, space, termScope, _, _) &*& [1/3]obligation_space(space, termScope) : true; predicate Q() = i < 9 ? [1/2]info->nextToSend |-> i + 1 : true; lemma void op() requires channel_inv(info)(?elems) &*& P(); ensures channel_inv(info)(append(elems, {(void *)i})) &*& Q(); { open channel_inv(info)(elems); open P(); is_range_append(info->nextToReceive, elems, info->nextToSend, {(void *)i}, info->nextToSend + 1); info->nextToSend++; close Q(); close channel_inv(info)(append(elems, {(void *)i})); } @*/ //@ produce_lemma_function_pointer_chunk(op) : channel_send_ghost_op(channel_inv(info), (void *)i, P, Q)() { call(); }; //@ close P(); //@ close exists(i == 9); //@ succ_int(0); //@ if (i == 9) { open debits(_, _); } channel_send(channel, (void *)i); //@ open Q(); } //@ succ_int(i); //@ succ_int(10 - i - 1); /*@ if (i < 9) { open debits(_, _); obspace_debit_dispose(); } @*/ } //@ open channel_send_tokens(0, _, _, _, _, _, _); //@ open debits(0, _); }
void * forward(void * ptr) { int err; msg_t tmp; channel_set s_chset, r_chset; s_chset.chan = chan_s; s_chset.events = CHANNEL_EVENT_READ|CHANNEL_EVENT_CLOSE; r_chset.chan = chan_r; r_chset.events = CHANNEL_EVENT_WRITE|CHANNEL_EVENT_CLOSE; while(n < MAX_FWD_MSG) { s_chset.revents = CHANNEL_EVENT_NOEVT; r_chset.revents = CHANNEL_EVENT_NOEVT; err = channel_select(&s_chset,1,CHANNEL_TIME_WAIT); if(err == -1) { perror("FWD - 1 channel_select()"); channel_close(chan_s); channel_close(chan_r); break; } else if(err == 0) continue; if(CHAN_READ_EVT(s_chset.revents)) { err = channel_recv(chan_s,&tmp); if(err == -1) { perror("FWD - error channel_recv"); channel_close(chan_s); channel_close(chan_r); break; } } else if(CHAN_CLOSE_EVT(s_chset.revents)) { channel_close(chan_r); break; } err = channel_select(&r_chset,1,CHANNEL_TIME_WAIT); if(err == -1) { perror("FWD - 1 channel_select()"); channel_close(chan_s); channel_close(chan_r); break; } else if(err == 0) continue; if(CHAN_WRITE_EVT(r_chset.revents)) { err = channel_send(chan_r,&tmp); if(err == -1) { perror("FWD - error channel_send"); channel_close(chan_s); channel_close(chan_r); break; } n += 1; if(n >= MAX_FWD_MSG) { //printf("n : %d OK \n",n); channel_close(chan_s); channel_close(chan_r); } } else if(CHAN_CLOSE_EVT(r_chset.revents)) { channel_close(chan_s); break; } } pthread_exit(NULL); }
void Environment::run(RunningContext *context) { const Instruction &ins = m_ipos; m_context = context; if (!context) { m_running = false; } else if (!m_running) { clear_vstore(); TRACE_PRINTF(TRACE_VM, TRACE_INFO, "Entering running state with %p\n", context); m_running = true; const SourcePos *last_pos = NULL; // used for debug output below. const Instruction *ipos; while (m_context && (ipos = m_context->next())) { size_t output = -1; size_t expected = -1; # define CHECK_STACK(in, out) TRACE_OUT(TRACE_VM, TRACE_SPAM) {\ assert(m_context->stack_count() >= (size_t)(in)); \ if ((out) != -1) { assert((long)(expected = m_context->stack_count() - (size_t)(in) + (size_t)(out)) >= 0); } \ tprintf("Stack info: before(%d), in(%d), out(%d), expected(%d)\n", (int)m_context->stack_count(), (int)(in), (int)(out), (int)expected); \ output = (out); \ } m_ipos = *ipos; TRACE_DO(TRACE_VM, TRACE_INFO) { const SourcePos &pos = m_context->m_instructions->source_pos(ipos); if (!last_pos || *last_pos != pos) tprintf("Source Position: %s:%d:%d (%s)\n", pos.file.c_str(), (int)pos.line_num, (int)pos.column, pos.annotation.c_str()); last_pos = &pos; } TRACE_OUT(TRACE_VM, TRACE_SPAM) { tprintf("Instruction: %s@%d\n", inspect(ins).c_str(), (int)(ipos - &*m_context->instructions().begin()) ); tprintf("Stack: %d deep", (int)m_context->stack_count()); const Value *it; for (it = m_context->stack_begin(); it != m_context->stack_pos(); it++) { tprintf("\n %s", inspect(*it).c_str()); } tprintf(" <--\n"); } switch(ins.instruction) { case NOP: CHECK_STACK(0, 0); break; case DEBUGGER: CHECK_STACK(0, 0); { String *action = ptr<String>(ins.arg1); if (*action == "interrupt") { DO_DEBUG __asm__("int3"); } else if (*action == "trace_enable") { trace_mute = false; } else if (*action == "trace_disable") { trace_mute = true; } } break; case POP: CHECK_STACK(1, 0); m_context->pop(); break; case PUSH: CHECK_STACK(0, 1); m_context->push(ins.arg1); break; case SWAP: { CHECK_STACK(2, 2); Value tmp1 = m_context->top(); m_context->pop(); Value tmp2 = m_context->top(); m_context->pop(); m_context->push(tmp1); m_context->push(tmp2); } break; case DUP_TOP: CHECK_STACK(1, 2); m_context->push(m_context->top()); break; case IS: { CHECK_STACK(1, 1); Value res = bvalue(ins.arg1 == m_context->top()); m_context->pop(); m_context->push(res); } break; case IS_EQ: { CHECK_STACK(2, 1); Value first = m_context->top(); m_context->pop(); Value second = m_context->top(); m_context->pop(); m_context->push(bvalue(first == second)); } break; case IS_NOT: { CHECK_STACK(1, 1); Value res = bvalue(ins.arg1 != m_context->top()); m_context->pop(); m_context->push(res); } break; case IS_NOT_EQ:{ CHECK_STACK(2, 1); Value first = m_context->top(); m_context->pop(); Value second = m_context->top(); m_context->pop(); m_context->push(bvalue(first != second)); } break; case JMP: CHECK_STACK(0, 0); GC::safe_point(); m_context->jump(ins.cache.machine_num); break; case JMP_IF: CHECK_STACK(1, 0); GC::safe_point(); if (is_truthy(m_context->top())) m_context->jump(ins.cache.machine_num); m_context->pop(); break; case JMP_IF_NOT: CHECK_STACK(1, 0); GC::safe_point(); if (!is_truthy(m_context->top())) m_context->jump(ins.cache.machine_num); m_context->pop(); break; case LEXICAL_CLEAN_SCOPE: { CHECK_STACK(0, 0); VariableFrame *frame = new_variable_frame(m_context->m_instructions); m_context->new_scope(frame); } break; case LEXICAL_LINKED_SCOPE: { CHECK_STACK(0, 0); VariableFrame *frame = new_variable_frame(m_context->m_instructions); frame->link_frame(m_context->m_lexicalvars); m_context->new_scope(frame); } break; case FRAME_GET: { CHECK_STACK(0, 1); size_t frameid = (size_t)ins.cache.machine_num; TRACE_PRINTF(TRACE_VM, TRACE_SPAM, "Getting frame var %s (%d)\n", ptr<String>(ins.arg1)->c_str(), (int)frameid); m_context->push(m_context->get_framevar(frameid)); } break; case FRAME_SET: { CHECK_STACK(1, 0); size_t frameid = (size_t)ins.cache.machine_num; TRACE_PRINTF(TRACE_VM, TRACE_SPAM, "Setting frame var %s (%d) to: %s\n", ptr<String>(ins.arg1)->c_str(), (int)frameid, inspect(m_context->top()).c_str()); m_context->set_framevar(frameid, m_context->top()); m_context->pop(); } break; case LOCAL_GET: { CHECK_STACK(0, 1); size_t localid = (size_t)ins.cache.machine_num; TRACE_PRINTF(TRACE_VM, TRACE_SPAM, "Getting local var %s (%d)\n", ptr<String>(ins.arg1)->c_str(), (int)localid); m_context->push(m_context->get_localvar(localid)); } break; case LOCAL_SET: { CHECK_STACK(1, 0); size_t localid = (size_t)ins.cache.machine_num; TRACE_PRINTF(TRACE_VM, TRACE_SPAM, "Setting local var %s (%d) to: %s\n", ptr<String>(ins.arg1)->c_str(), (int)localid, inspect(m_context->top()).c_str()); m_context->set_localvar(localid, m_context->top()); m_context->pop(); } break; case LEXICAL_GET: { CHECK_STACK(0, 1); size_t depth = ins.arg1.machine_num; size_t localid = (size_t)ins.cache.machine_num; TRACE_PRINTF(TRACE_VM, TRACE_SPAM, "lexical_get %u@%u: %i\n", (unsigned)localid, (unsigned)depth, type(m_context->get_lexicalvar(localid, depth))); if (depth == 0) m_context->push(m_context->get_lexicalvar(localid)); else m_context->push(m_context->get_lexicalvar(localid, depth)); } break; case LEXICAL_SET: { CHECK_STACK(1, 0); size_t depth = ins.arg1.machine_num; size_t localid = (size_t)ins.cache.machine_num; TRACE_PRINTF(TRACE_VM, TRACE_SPAM, "lexical_set %u@%u: %i\n", (unsigned)localid, (unsigned)depth, type(m_context->top())); if (depth == 0) m_context->set_lexicalvar(localid, m_context->top()); else m_context->set_lexicalvar(localid, depth, m_context->top()); m_context->pop(); } break; case CHANNEL_NEW: { CHECK_STACK(0, 1); const Value &octx = vstore(value(m_context)); RunnableContext *nctx = new_context(octx); nctx->jump(ins.cache.machine_num); m_context->push(value(nctx)); clear_vstore(); } break; case CHANNEL_SPECIAL: CHECK_STACK(0, 1); m_context->push(special_channel(*ptr<String>(ins.arg1))); break; case CHANNEL_SEND: { CHECK_STACK(3, -1); GC::safe_point(); const Value &val = vstore(m_context->top()); m_context->pop(); const Value &ret = vstore(m_context->top()); m_context->pop(); const Value &channel = vstore(m_context->top()); m_context->pop(); // A context that's been channel_sended from should never be returned to, // so invalidate it. m_context->invalidate(); channel_send(this, channel, val, ret); clear_vstore(); } break; case CHANNEL_CALL:{ CHECK_STACK(2, -1); GC::safe_point(); const Value &val = vstore(m_context->top()); m_context->pop(); const Value &channel = vstore(m_context->top()); m_context->pop(); const Value &ret = vstore(value(m_context)); channel_send(this, channel, val, ret); clear_vstore(); } break; case CHANNEL_RET:{ CHECK_STACK(2, -1); const Value &val = vstore(m_context->top()); m_context->pop(); const Value &channel = vstore(m_context->top()); m_context->pop(); // A context that's been channel_reted from should never be returned to, // so invalidate it. m_context->invalidate(); channel_send(this, channel, val, value(&no_return_ctx)); clear_vstore(); } break; case MESSAGE_NEW: { long long id = ins.cache.machine_num; long long sysarg_count = ins.arg2.machine_num, sysarg_counter = sysarg_count - 1; long long arg_count = ins.arg3.machine_num, arg_counter = arg_count - 1; CHECK_STACK(sysarg_count + arg_count, 1); Message *msg = new_message(id, sysarg_count, arg_count); while (arg_count > 0 && arg_counter >= 0) { msg->args()[arg_counter] = m_context->top(); m_context->pop(); --arg_counter; } while (sysarg_count > 0 && sysarg_counter >= 0) { msg->sysargs()[sysarg_counter] = m_context->top(); m_context->pop(); --sysarg_counter; } m_context->push(value(msg)); } break; case MESSAGE_SPLAT: { CHECK_STACK(2, 1); const Tuple &tuple = *ptr<Tuple>(m_context->top()); m_context->pop(); const Message &msg = *ptr<Message>(m_context->top()); m_context->pop(); Message *nmsg = new_message(msg.m_id, msg.sysarg_count(), msg.arg_count() + tuple.size()); std::copy(msg.sysargs(), msg.sysargs_end(), nmsg->sysargs()); std::copy(msg.args(), msg.args_end(), nmsg->args()); std::copy(tuple.begin(), tuple.end(), nmsg->args() + msg.arg_count()); m_context->push(value(nmsg)); } break; case MESSAGE_ADD: { long long count = ins.arg1.machine_num, counter = 0; CHECK_STACK(1 + count, 1); const Message &msg = *ptr<Message>(*(m_context->stack_pos() - 1 - count)); Message *nmsg = new_message(msg.m_id, msg.sysarg_count(), msg.arg_count() + count); std::copy(msg.sysargs(), msg.sysargs_end(), nmsg->sysargs()); std::copy(msg.args(), msg.args_end(), nmsg->args()); Message::iterator out = nmsg->args() + msg.arg_count(); while (count > 0 && counter < count) { *out++ = m_context->top(); m_context->pop(); ++counter; } m_context->pop(); // this is the message we pulled directly off the stack before. m_context->push(value(nmsg)); } break; case MESSAGE_COUNT: CHECK_STACK(1, 2); m_context->push(value((long long)ptr<Message>(m_context->top())->arg_count())); break; case MESSAGE_IS: CHECK_STACK(1, 2); m_context->push(bvalue(ptr<Message>(m_context->top())->m_id == (uint64_t)ins.cache.machine_num)); break; case MESSAGE_IS_PROTO: CHECK_STACK(1, 2); m_context->push(bvalue(ptr<Message>(m_context->top())->protocol_id() == (uint64_t)ins.cache.machine_num)); break; case MESSAGE_ID: { CHECK_STACK(1, 2); Message *msg = ptr<Message>(m_context->top()); m_context->push(value((long long)msg->m_id)); } break; case MESSAGE_SPLIT_ID: { CHECK_STACK(1, 3); Message *msg = ptr<Message>(m_context->top()); m_context->push(value((long long)msg->message_id())); m_context->push(value((long long)msg->protocol_id())); } break; case MESSAGE_CHECK: CHECK_STACK(1, 1); if (!is(m_context->top(), MESSAGE)) { m_context->pop(); m_context->push(False); } break; case MESSAGE_FORWARD: { CHECK_STACK(1, 1); long long id = ins.cache.machine_num; const Message &msg = *ptr<Message>(m_context->top()); Message *nmsg = new_message(id, msg.sysarg_count(), msg.arg_count() + 1); std::copy(msg.sysargs(), msg.sysargs_end(), nmsg->sysargs()); nmsg->args()[0] = value(new_string(msg.name())); std::copy(msg.args(), msg.args_end(), nmsg->args() + 1); m_context->pop(); m_context->push(value(nmsg)); break; } case MESSAGE_SYS_PREFIX: { long long count = ins.arg1.machine_num, counter = 0; CHECK_STACK(1 + count, 1); const Value *sdata = m_context->stack_pos() - 1 - count; const Message &msg = *ptr<Message>(*sdata++); Message *nmsg = new_message(msg.m_id, msg.sysarg_count() + count, msg.arg_count()); Message::iterator to = nmsg->sysargs(); while (counter++ < count) { *to++ = *sdata++; } std::copy(msg.sysargs(), msg.sysargs_end(), to); std::copy(msg.args(), msg.args_end(), nmsg->args()); while (--counter != 0) { m_context->pop(); } m_context->pop(); // message we read off stack before. m_context->push(value(nmsg)); break; } case MESSAGE_SYS_UNPACK: { long long count = ins.arg1.machine_num, pos = count - 1; CHECK_STACK(1, 1 + count); const Message *msg = ptr<Message>(m_context->top()); Message::const_iterator args = msg->sysargs(); long long len = (long long)msg->sysarg_count(); while (pos >= 0) { if (pos >= len) m_context->push(Undef); else m_context->push(args[pos]); pos -= 1; } } break; case MESSAGE_UNPACK: { long long first_count = ins.arg1.machine_num, first_counter = 0; long long splat = ins.arg2.machine_num; long long last_count = ins.arg3.machine_num, last_counter = 0; CHECK_STACK(1, 1 + first_count + last_count + (splat?1:0)); const Message *msg = ptr<Message>(m_context->top()); Message::const_iterator args = msg->args(); long long len = (long long)msg->arg_count(), pos = len - 1; while (last_counter < last_count && pos >= first_count) { if (pos >= len) m_context->push(Nil); else m_context->push(args[pos]); pos -= 1; last_counter += 1; } if (splat != 0) { if (pos >= first_count) { Tuple *splat_tuple = new_tuple(pos - first_count + 1); Tuple::iterator out = splat_tuple->end(); while (pos >= first_count) { --out; *out = args[pos]; pos -= 1; } m_context->push(value(splat_tuple)); } else { m_context->push(value(new_tuple(0))); } } pos = first_count - 1; while (first_counter < first_count && pos >= 0) { if (pos >= len) m_context->push(Nil); else m_context->push(args[pos]); pos -= 1; first_counter += 1; } } break; case STRING_COERCE: { const Value &coerce = ins.arg1; const Value &val = vstore(m_context->top()); if (is(val, STRING)) { CHECK_STACK(1, 2); // push a nil like we called the method. m_context->push(Nil); } else { CHECK_STACK(1, -1); m_context->pop(); channel_send(this, val, value(new_message(coerce)), value(m_context)); } } clear_vstore(); break; case STRING_NEW: { long long count = ins.arg1.machine_num, counter = 0; CHECK_STACK(count, 1); const Value *sp = m_context->stack_pos() - 1; size_t len = 0; while (count > 0 && counter < count) { assert(is(sp[-counter], STRING)); len += ptr<String>(sp[-counter])->length(); ++counter; } String *res = new_string(len); String::iterator out = res->begin(); counter = 0; while (count > 0 && counter < count) { const String *val = ptr<String>(m_context->top()); out = std::copy(val->begin(), val->end(), out); m_context->pop(); ++counter; } m_context->push(value(res)); } break; case TUPLE_NEW: { long long count = ins.arg1.machine_num, counter = 0; CHECK_STACK(count, 1); Tuple *tuple = new_tuple(count); Tuple::iterator out = tuple->begin(); while (count > 0 && counter < count) { *out++ = m_context->top(); m_context->pop(); ++counter; } m_context->push(value(tuple)); } break; case TUPLE_SPLAT: { CHECK_STACK(2, 1); const Tuple *tuple2 = ptr<Tuple>(m_context->top()); m_context->pop(); const Tuple *tuple1 = ptr<Tuple>(m_context->top()); m_context->pop(); Tuple *tuple = join_tuple(tuple1, tuple2); m_context->push(value(tuple)); } break; case TUPLE_UNPACK: { long long first_count = ins.arg1.machine_num, first_counter = 0; long long splat = ins.arg2.machine_num; long long last_count = ins.arg3.machine_num, last_counter = 0; CHECK_STACK(1, 1 + first_count + last_count + (splat?1:0)); const Tuple &tuple = *ptr<Tuple>(m_context->top()); long long len = tuple.size(), pos = tuple.size() - 1; while (last_counter < last_count && pos >= first_count) { if (pos >= len) m_context->push(Nil); else m_context->push(tuple[pos]); pos -= 1; last_counter += 1; } if (splat != 0) { if (pos >= first_count) { Tuple *splat_tuple = new_tuple(pos - first_count + 1); Tuple::iterator out = splat_tuple->end(); while (pos >= first_count) { --out; *out = tuple[pos]; pos -= 1; } m_context->push(value(splat_tuple)); } else { m_context->push(value(new_tuple(0))); } } pos = first_count - 1; while (first_counter < first_count && pos >= 0) { if (pos >= len) m_context->push(Nil); else m_context->push(tuple[pos]); pos -= 1; first_counter += 1; } } break; default: printf("Panic! Unknown instruction %d\n", ins.instruction); exit(1); } TRACE_OUT(TRACE_VM, TRACE_SPAM) { tprintf("Output: %d", (int)output); if ((long)output > 0) { const Value *it = std::max( m_context->stack_begin(), m_context->stack_pos() - output); for (; it != m_context->stack_pos(); it++) { tprintf("\n %s", inspect(*it).c_str()); } } tprintf(" <--\n"); tprintf("----------------\n"); }
void evnet_channelsend(void* c, char *data, int size) { channel_send((channel_t*)c, data, size); }
/* -------------------------------------------------------------------------- * * argv[0] - prefix * * argv[1] - 'ntopic' * * argv[2] - channel * * argv[3] - channel ts * * argv[4] - topic info * * argv[5] - topic time * * argv[6] - topic * * -------------------------------------------------------------------------- */ static void ms_ntopic(struct lclient *lcptr, struct client *cptr, int argc, char **argv) { struct channel *chptr; time_t ts; time_t topic_ts; int changed = 0; char topic[IRCD_TOPICLEN]; topic[0] = '\0'; if(argc == 7) strlcpy(topic, argv[6], sizeof(topic)); if((chptr = channel_find_name(argv[2])) == NULL) { log(client_log, L_warning, "Dropping invalid NTOPIC for channel %s.", argv[2]); return; } ts = str_toul(argv[3], NULL, 10); if(ts > chptr->ts || chptr->topic[0]) { log(client_log, L_verbose, "Dropping NTOPIC for %s with too recent TS", chptr->name); return; } topic_ts = str_toul(argv[5], NULL, 10); if(chptr->ts == ts) { if(chptr->topic_ts > topic_ts) { log(client_log, L_verbose, "Dropping NTOPIC for %s because its older", chptr->name); return; } if(chptr->topic_ts == topic_ts) { size_t nlen; size_t olen; nlen = topic[0] ? str_len(topic) : 0; olen = str_len(chptr->topic); if(nlen < olen) { log(client_log, L_warning, "TOPIC collision on %s, ignoring.", chptr->name); return; } if(nlen == olen) { if((topic == NULL && chptr->topic[0] == '\0')) return; if(!str_cmp(topic, chptr->topic)) return; } } } if(chptr->ts != ts) { log(channel_log, L_warning, "TS for channel %s changed from %lu to %lu.", chptr->name, chptr->ts, ts); chptr->ts = ts; } if(str_cmp(chptr->topic, topic)) changed = 1; if(changed) { if(topic[0]) strlcpy(chptr->topic, topic, sizeof(chptr->topic)); else chptr->topic[0] = '\0'; } strlcpy(chptr->topic_info, argv[4], sizeof(chptr->topic_info)); chptr->topic_ts = topic_ts; if(chptr->topic[0]) server_send(lcptr, NULL, CAP_NONE, CAP_NONE, ":%C NTOPIC %s %lu %s %lu :%s", cptr, chptr->name, chptr->ts, chptr->topic_info, chptr->topic_ts, chptr->topic); else server_send(lcptr, NULL, CAP_NONE, CAP_NONE, ":%C NTOPIC %s %lu %s %lu", cptr, chptr->name, chptr->ts, chptr->topic_info, chptr->topic_ts); if(changed) { channel_send(NULL, chptr, CHFLG(NONE), CHFLG(NONE), ":%C TOPIC %s :%s", cptr, chptr->name, chptr->topic); } }