void pit_isr0() //电机控制5ms { //读脉冲 pulsecount = LPLD_LPTMR_GetPulseAcc(); pulseaccu += pulsecount; //pulsetotal+=pulsecount; LPLD_LPTMR_Reset(); LPLD_LPTMR_Init(MODE_PLACC, 0, LPTMR_ALT1, IRQ_DISABLE, NULL); //分析 // analyse(); //控制 scan_infrared(r1, r2, r3, r4); //fisrthongwaierror(); //secondhongwaierror();//边沿跳变获得误差 calculate_infrared_error(r1, INFRARED_LINE1_NUM, &r1_error); calculate_infrared_error(r2, INFRARED_LINE2_NUM, &r2_error); if (is_enabled) do_control(); else do_stop(); static int __scan_infront_counter = 0; if (__adc > SCAN_INFRONT_THRESHOLE_SMALL && abs(r1_error - r2_error) < 2) __scan_infront_counter ++; else { __scan_infront_counter = 0; } is_car_infront = __scan_infront_counter > 5; }
int process(char **args) { int return_val = 0; if (args[0] == NULL) { return_val = 0; } else if (is_control(args[0])) { return_val = do_control(args); } else if (is_ok()) { if (!internal(args, &return_val)) { return_val = execute(args); } } return return_val; }
/* * Service a request from the pmlogger client. * Return non-zero if the client has closed the connection. */ int client_req(void) { int sts; __pmPDU *pb; __pmPDUHdr *php; int pinpdu; if ((pinpdu = sts = __pmGetPDU(clientfd, ANY_SIZE, TIMEOUT_DEFAULT, &pb)) <= 0) { if (sts != 0) fprintf(stderr, "client_req: %s\n", pmErrStr(sts)); return 1; } if (qa_case == QA_SLEEPY) { /* error injection - delay before processing and responding */ sleep(5); } php = (__pmPDUHdr *)pb; sts = 0; switch (php->type) { case PDU_CREDS: /* version 2 PDU */ sts = do_creds(pb); break; case PDU_LOG_REQUEST: /* version 2 PDU */ sts = do_request(pb); break; case PDU_LOG_CONTROL: /* version 2 PDU */ sts = do_control(pb); break; default: /* unknown PDU */ fprintf(stderr, "client_req: bad PDU type 0x%x\n", php->type); sts = PM_ERR_IPC; break; } if (pinpdu > 0) __pmUnpinPDUBuf(pb); if (sts >= 0) return 0; else { /* the client isn't playing by the rules */ __pmSendError(clientfd, FROM_ANON, sts); return 1; } }
static void do_service(config_t *cpe, config_t *config, struct rs_config *rs_config) { struct rs_start *rs_start = &rs_config->rs_start; config_t *cp; /* At this point we expect one sublist that contains the varios * resource allocations */ if (!(cpe->flags & CFG_SUBLIST)) { fatal("do_service: expected list at %s:%d", cpe->file, cpe->line); } if (cpe->next != NULL) { cpe= cpe->next; fatal("do_service: expected end of list at %s:%d", cpe->file, cpe->line); } cpe= cpe->list; /* Process the list */ for (cp= cpe; cp; cp= cp->next) { if (!(cp->flags & CFG_SUBLIST)) { fatal("do_service: expected list at %s:%d", cp->file, cp->line); } cpe= cp->list; if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) { fatal("do_service: expected word at %s:%d", cpe->file, cpe->line); } if (strcmp(cpe->word, KW_CLASS) == 0) { do_class(cpe->next, config, rs_config); continue; } if (strcmp(cpe->word, KW_UID) == 0) { do_uid(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_SIGMGR) == 0) { do_sigmgr(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_TYPE) == 0) { do_type(cpe->next, rs_config); continue; } if (strcmp(cpe->word, KW_DESCR) == 0) { do_descr(cpe->next, rs_config); continue; } if (strcmp(cpe->word, KW_SCHEDULER) == 0) { do_scheduler(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_PRIORITY) == 0) { do_priority(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_QUANTUM) == 0) { do_quantum(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_CPU) == 0) { do_cpu(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_IRQ) == 0) { do_irq(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_IO) == 0) { do_io(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_PCI) == 0) { do_pci(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_SYSTEM) == 0) { do_system(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_IPC) == 0) { do_ipc(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_VM) == 0) { do_vm(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_CONTROL) == 0) { do_control(cpe->next, rs_start); continue; } } }
void network_thread () { /* * We loop forever waiting on either data from the ppp drivers or from * our network socket. Control handling is no longer done here. */ struct sockaddr_in from; struct in_pktinfo to; unsigned int fromlen; int tunnel, call; /* Tunnel and call */ int recvsize; /* Length of data received */ struct buffer *buf; /* Payload buffer */ struct call *c, *sc; /* Call to send this off to */ struct tunnel *st; /* Tunnel */ fd_set readfds; /* Descriptors to watch for reading */ int max; /* Highest fd */ struct timeval tv, *ptv; /* Timeout for select */ struct msghdr msgh; struct iovec iov; char cbuf[256]; unsigned int refme, refhim; int * currentfd; int server_socket_processed; #ifdef HIGH_PRIO /* set high priority */ if (setpriority(PRIO_PROCESS, 0, -20) < 0) l2tp_log (LOG_INFO, "xl2tpd: can't set priority to high: %m"); #endif /* This one buffer can be recycled for everything except control packets */ buf = new_buf (MAX_RECV_SIZE); tunnel = 0; call = 0; for (;;) { int ret; process_signal(); max = build_fdset (&readfds); ptv = process_schedule(&tv); ret = select (max + 1, &readfds, NULL, NULL, ptv); if (ret <= 0) { #ifdef DEBUG_MORE if (ret == 0) { if (gconfig.debug_network) { l2tp_log (LOG_DEBUG, "%s: select timeout\n", __FUNCTION__); } } else { if (gconfig.debug_network) { l2tp_log (LOG_DEBUG, "%s: select returned error %d (%s)\n", __FUNCTION__, errno, strerror (errno)); } } #endif continue; } if (FD_ISSET (control_fd, &readfds)) { do_control (); } server_socket_processed = 0; currentfd = NULL; st = tunnels.head; while (st || !server_socket_processed) { if (st && (st->udp_fd == -1)) { st=st->next; continue; } if (st) { currentfd = &st->udp_fd; } else { currentfd = &server_socket; server_socket_processed = 1; } if (FD_ISSET (*currentfd, &readfds)) { /* * Okay, now we're ready for reading and processing new data. */ recycle_buf (buf); /* Reserve space for expanding payload packet headers */ buf->start += PAYLOAD_BUF; buf->len -= PAYLOAD_BUF; memset(&from, 0, sizeof(from)); memset(&to, 0, sizeof(to)); fromlen = sizeof(from); memset(&msgh, 0, sizeof(struct msghdr)); iov.iov_base = buf->start; iov.iov_len = buf->len; msgh.msg_control = cbuf; msgh.msg_controllen = sizeof(cbuf); msgh.msg_name = &from; msgh.msg_namelen = fromlen; msgh.msg_iov = &iov; msgh.msg_iovlen = 1; msgh.msg_flags = 0; /* Receive one packet. */ recvsize = recvmsg(*currentfd, &msgh, 0); if (recvsize < MIN_PAYLOAD_HDR_LEN) { if (recvsize < 0) { if (errno == ECONNREFUSED) { close(*currentfd); } if ((errno == ECONNREFUSED) || (errno == EBADF)) { *currentfd = -1; } if (errno != EAGAIN) l2tp_log (LOG_WARNING, "%s: recvfrom returned error %d (%s)\n", __FUNCTION__, errno, strerror (errno)); } else { l2tp_log (LOG_WARNING, "%s: received too small a packet\n", __FUNCTION__); } if (st) st=st->next; continue; } refme=refhim=0; struct cmsghdr *cmsg; /* Process auxiliary received data in msgh */ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh,cmsg)) { /* extract destination(our) addr */ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { struct in_pktinfo* pktInfo = ((struct in_pktinfo*)CMSG_DATA(cmsg)); to = *pktInfo; } /* extract IPsec info out */ else if (gconfig.ipsecsaref && cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == gconfig.sarefnum) { unsigned int *refp; refp = (unsigned int *)CMSG_DATA(cmsg); refme =refp[0]; refhim=refp[1]; } } /* * some logic could be added here to verify that we only * get L2TP packets inside of IPsec, or to provide different * classes of service to packets not inside of IPsec. */ buf->len = recvsize; fix_hdr (buf->start); extract (buf->start, &tunnel, &call); if (gconfig.debug_network) { l2tp_log(LOG_DEBUG, "%s: recv packet from %s, size = %d, " "tunnel = %d, call = %d ref=%u refhim=%u\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call, refme, refhim); } if (gconfig.packet_dump) { do_packet_dump (buf); } if (!(c = get_call (tunnel, call, from.sin_addr, from.sin_port, refme, refhim))) { if ((c = get_tunnel (tunnel, from.sin_addr.s_addr, from.sin_port))) { /* * It is theoretically possible that we could be sent * a control message (say a StopCCN) on a call that we * have already closed or some such nonsense. To * prevent this from closing the tunnel, if we get a * call on a valid tunnel, but not with a valid CID, * we'll just send a ZLB to ack receiving the packet. */ if (gconfig.debug_tunnel) l2tp_log (LOG_DEBUG, "%s: no such call %d on tunnel %d. Sending special ZLB\n", __FUNCTION__, call, tunnel); if (handle_special (buf, c, call) == 0) /* get a new buffer */ buf = new_buf (MAX_RECV_SIZE); } #ifdef DEBUG_MORE else{ l2tp_log (LOG_DEBUG, "%s: unable to find call or tunnel to handle packet. call = %d, tunnel = %d Dumping.\n", __FUNCTION__, call, tunnel); } #endif } else { if (c->container) { c->container->my_addr = to; } buf->peer = from; /* Handle the packet */ c->container->chal_us.vector = NULL; if (handle_packet (buf, c->container, c)) { if (gconfig.debug_tunnel) l2tp_log (LOG_DEBUG, "%s: bad packet\n", __FUNCTION__); } if (c->cnu) { /* Send Zero Byte Packet */ control_zlb (buf, c->container, c); c->cnu = 0; } } } if (st) st=st->next; } /* * finished obvious sources, look for data from PPP connections. */ st = tunnels.head; while (st) { sc = st->call_head; while (sc) { if ((sc->fd >= 0) && FD_ISSET (sc->fd, &readfds)) { /* Got some payload to send */ int result; while ((result = read_packet (sc)) > 0) { add_payload_hdr (sc->container, sc, sc->ppp_buf); if (gconfig.packet_dump) { do_packet_dump (sc->ppp_buf); } sc->prx = sc->data_rec_seq_num; if (sc->zlb_xmit) { deschedule (sc->zlb_xmit); sc->zlb_xmit = NULL; } sc->tx_bytes += sc->ppp_buf->len; sc->tx_pkts++; udp_xmit (sc->ppp_buf, st); recycle_payload (sc->ppp_buf, sc->container->peer); } if (result != 0) { l2tp_log (LOG_WARNING, "%s: tossing read packet, error = %s (%d). Closing call.\n", __FUNCTION__, strerror (-result), -result); strcpy (sc->errormsg, strerror (-result)); sc->needclose = -1; } } sc = sc->next; } st = st->next; } } }
void network_thread () { /* * We loop forever waiting on either data from the ppp drivers or from * our network socket. Control handling is no longer done here. */ struct sockaddr_in from, to; unsigned int fromlen, tolen; int tunnel, call; /* Tunnel and call */ int recvsize; /* Length of data received */ struct buffer *buf; /* Payload buffer */ struct call *c, *sc; /* Call to send this off to */ struct tunnel *st; /* Tunnel */ fd_set readfds; /* Descriptors to watch for reading */ int max; /* Highest fd */ struct timeval tv, *ptv; /* Timeout for select */ struct msghdr msgh; struct iovec iov; char cbuf[256]; unsigned int refme, refhim; /* This one buffer can be recycled for everything except control packets */ buf = new_buf (MAX_RECV_SIZE); tunnel = 0; call = 0; for (;;) { int ret; process_signal(); max = build_fdset (&readfds); ptv = process_schedule(&tv); ret = select (max + 1, &readfds, NULL, NULL, ptv); if (ret <= 0) { if (ret == 0) { if (gconfig.debug_network) { l2tp_log (LOG_DEBUG, "%s: select timeout\n", __FUNCTION__); } } else { if (gconfig.debug_network) { l2tp_log (LOG_DEBUG, "%s: select returned error %d (%s)\n", __FUNCTION__, errno, strerror (errno)); } } continue; } if (FD_ISSET (control_fd, &readfds)) { do_control (); } if (FD_ISSET (server_socket, &readfds)) { /* * Okay, now we're ready for reading and processing new data. */ recycle_buf (buf); /* Reserve space for expanding payload packet headers */ buf->start += PAYLOAD_BUF; buf->len -= PAYLOAD_BUF; memset(&from, 0, sizeof(from)); memset(&to, 0, sizeof(to)); fromlen = sizeof(from); tolen = sizeof(to); memset(&msgh, 0, sizeof(struct msghdr)); iov.iov_base = buf->start; iov.iov_len = buf->len; msgh.msg_control = cbuf; msgh.msg_controllen = sizeof(cbuf); msgh.msg_name = &from; msgh.msg_namelen = fromlen; msgh.msg_iov = &iov; msgh.msg_iovlen = 1; msgh.msg_flags = 0; /* Receive one packet. */ recvsize = recvmsg(server_socket, &msgh, 0); if (recvsize < MIN_PAYLOAD_HDR_LEN) { if (recvsize < 0) { if (errno != EAGAIN) l2tp_log (LOG_WARNING, "%s: recvfrom returned error %d (%s)\n", __FUNCTION__, errno, strerror (errno)); } else { l2tp_log (LOG_WARNING, "%s: received too small a packet\n", __FUNCTION__); } continue; } refme=refhim=0; /* extract IPsec info out */ if(gconfig.ipsecsaref) { struct cmsghdr *cmsg; /* Process auxiliary received data in msgh */ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh,cmsg)) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_IPSEC_REFINFO) { unsigned int *refp; refp = (unsigned int *)CMSG_DATA(cmsg); refme =refp[0]; refhim=refp[1]; } } } /* * some logic could be added here to verify that we only * get L2TP packets inside of IPsec, or to provide different * classes of service to packets not inside of IPsec. */ buf->len = recvsize; fix_hdr (buf->start); extract (buf->start, &tunnel, &call); if (gconfig.debug_network) { l2tp_log(LOG_DEBUG, "%s: recv packet from %s, size = %d, " "tunnel = %d, call = %d ref=%u refhim=%u\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call, refme, refhim); } if (gconfig.packet_dump) { do_packet_dump (buf); } if (! (c = get_call (tunnel, call, from.sin_addr.s_addr, from.sin_port, refme, refhim))) { if ((c = get_tunnel (tunnel, from.sin_addr.s_addr, from.sin_port))) { /* * It is theoretically possible that we could be sent * a control message (say a StopCCN) on a call that we * have already closed or some such nonsense. To * prevent this from closing the tunnel, if we get a * call on a valid tunnel, but not with a valid CID, * we'll just send a ZLB to ack receiving the packet. */ if (gconfig.debug_tunnel) l2tp_log (LOG_DEBUG, "%s: no such call %d on tunnel %d. Sending special ZLB\n", __FUNCTION__); handle_special (buf, c, call); /* get a new buffer */ buf = new_buf (MAX_RECV_SIZE); } else l2tp_log (LOG_DEBUG, "%s: unable to find call or tunnel to handle packet. call = %d, tunnel = %d Dumping.\n", __FUNCTION__, call, tunnel); } else { buf->peer = from; /* Handle the packet */ c->container->chal_us.vector = NULL; if (handle_packet (buf, c->container, c)) { if (gconfig.debug_tunnel) l2tp_log (LOG_DEBUG, "%s: bad packet\n", __FUNCTION__); }; if (c->cnu) { /* Send Zero Byte Packet */ control_zlb (buf, c->container, c); c->cnu = 0; } }; } /* * finished obvious sources, look for data from PPP connections. */ st = tunnels.head; while (st) { sc = st->call_head; while (sc) { if ((sc->fd >= 0) && FD_ISSET (sc->fd, &readfds)) { /* Got some payload to send */ int result; recycle_payload (buf, sc->container->peer); /* #ifdef DEBUG_FLOW_MORE l2tp_log (LOG_DEBUG, "%s: rws = %d, pSs = %d, pLr = %d\n", __FUNCTION__, sc->rws, sc->pSs, sc->pLr); #endif if ((sc->rws>0) && (sc->pSs > sc->pLr + sc->rws) && !sc->rbit) { #ifdef DEBUG_FLOW log(LOG_DEBUG, "%s: throttling payload (call = %d, tunnel = %d, Lr = %d, Ss = %d, rws = %d)!\n",__FUNCTION__, sc->cid, sc->container->tid, sc->pLr, sc->pSs, sc->rws); #endif sc->throttle = -1; We unthrottle in handle_packet if we get a payload packet, valid or ZLB, but we also schedule a dethrottle in which case the R-bit will be set FIXME: Rate Adaptive timeout? tv.tv_sec = 2; tv.tv_usec = 0; sc->dethrottle = schedule(tv, dethrottle, sc); } else */ /* while ((result=read_packet(buf,sc->fd,sc->frame & SYNC_FRAMING))>0) { */ while ((result = read_packet (buf, sc->fd, SYNC_FRAMING)) > 0) { add_payload_hdr (sc->container, sc, buf); if (gconfig.packet_dump) { do_packet_dump (buf); } sc->prx = sc->data_rec_seq_num; if (sc->zlb_xmit) { deschedule (sc->zlb_xmit); sc->zlb_xmit = NULL; } sc->tx_bytes += buf->len; sc->tx_pkts++; udp_xmit (buf, st); recycle_payload (buf, sc->container->peer); } if (result != 0) { l2tp_log (LOG_WARNING, "%s: tossing read packet, error = %s (%d). Closing call.\n", __FUNCTION__, strerror (-result), -result); strcpy (sc->errormsg, strerror (-result)); sc->needclose = -1; } } sc = sc->next; } st = st->next; } } }
void snd_midi_process_event(struct snd_midi_op *ops, struct snd_seq_event *ev, struct snd_midi_channel_set *chanset) { struct snd_midi_channel *chan; void *drv; int dest_channel = 0; if (ev == NULL || chanset == NULL) { snd_printd("ev or chanbase NULL (snd_midi_process_event)\n"); return; } if (chanset->channels == NULL) return; if (snd_seq_ev_is_channel_type(ev)) { dest_channel = ev->data.note.channel; if (dest_channel >= chanset->max_channels) { snd_printd("dest channel is %d, max is %d\n", dest_channel, chanset->max_channels); return; } } chan = chanset->channels + dest_channel; drv = chanset->private_data; if (ev->type == SNDRV_SEQ_EVENT_NOTE) return; if (ev->type == SNDRV_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0) ev->type = SNDRV_SEQ_EVENT_NOTEOFF; if (ev->type == SNDRV_SEQ_EVENT_NOTEON || ev->type == SNDRV_SEQ_EVENT_NOTEOFF || ev->type == SNDRV_SEQ_EVENT_KEYPRESS) { if (ev->data.note.note >= 128) return; } switch (ev->type) { case SNDRV_SEQ_EVENT_NOTEON: if (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON) { if (ops->note_off) ops->note_off(drv, ev->data.note.note, 0, chan); } chan->note[ev->data.note.note] = SNDRV_MIDI_NOTE_ON; if (ops->note_on) ops->note_on(drv, ev->data.note.note, ev->data.note.velocity, chan); break; case SNDRV_SEQ_EVENT_NOTEOFF: if (! (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON)) break; if (ops->note_off) note_off(ops, drv, chan, ev->data.note.note, ev->data.note.velocity); break; case SNDRV_SEQ_EVENT_KEYPRESS: if (ops->key_press) ops->key_press(drv, ev->data.note.note, ev->data.note.velocity, chan); break; case SNDRV_SEQ_EVENT_CONTROLLER: do_control(ops, drv, chanset, chan, ev->data.control.param, ev->data.control.value); break; case SNDRV_SEQ_EVENT_PGMCHANGE: chan->midi_program = ev->data.control.value; break; case SNDRV_SEQ_EVENT_PITCHBEND: chan->midi_pitchbend = ev->data.control.value; if (ops->control) ops->control(drv, MIDI_CTL_PITCHBEND, chan); break; case SNDRV_SEQ_EVENT_CHANPRESS: chan->midi_pressure = ev->data.control.value; if (ops->control) ops->control(drv, MIDI_CTL_CHAN_PRESSURE, chan); break; case SNDRV_SEQ_EVENT_CONTROL14: if (ev->data.control.param < 32) { chan->control[ev->data.control.param + 32] = ev->data.control.value & 0x7f; do_control(ops, drv, chanset, chan, ev->data.control.param, ((ev->data.control.value>>7) & 0x7f)); } else
void network_thread () { /* * We loop forever waiting on either data from the ppp drivers or from * our network socket. Control handling is no longer done here. */ int fromlen; /* Length of the address */ int tunnel, call; /* Tunnel and call */ int recvsize; /* Length of data received */ struct buffer *buf; /* Payload buffer */ struct call *c, *sc; /* Call to send this off to */ struct tunnel *st; /* Tunnel */ fd_set readfds; /* Descriptors to watch for reading */ int max; /* Highest fd */ struct timeval tv; /* Timeout for select */ /* This one buffer can be recycled for everything except control packets */ buf = new_buf (MAX_RECV_SIZE); gconfig.debug_tunnel = 1; for (;;) { max = build_fdset (&readfds); tv.tv_sec = 1; tv.tv_usec = 0; schedule_unlock (); select (max + 1, &readfds, NULL, NULL, NULL); schedule_lock (); if (FD_ISSET (control_fd, &readfds)) { do_control (); } if (FD_ISSET (server_socket, &readfds)) { /* * Okay, now we're ready for reading and processing new data. */ recycle_buf (buf); /* Reserve space for expanding payload packet headers */ buf->start += PAYLOAD_BUF; buf->len -= PAYLOAD_BUF; fromlen = sizeof (from); recvsize = recvfrom (server_socket, buf->start, buf->len, 0, (struct sockaddr *) &from, &fromlen); if (recvsize < MIN_PAYLOAD_HDR_LEN) { if (recvsize < 0) { if (errno != EAGAIN) log (LOG_WARN, "%s: recvfrom returned error %d (%s)\n", __FUNCTION__, errno, strerror (errno)); } else { log (LOG_WARN, "%s: received too small a packet\n", __FUNCTION__); } } else { buf->len = recvsize; if (gconfig.debug_network) { log (LOG_DEBUG, "%s: recv packet from %s, size = %d, " "tunnel = %d, call = %d\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call); } if (gconfig.packet_dump) { do_packet_dump (buf); } fix_hdr (buf->start); extract (buf->start, &tunnel, &call); if (! (c = get_call (tunnel, call, from.sin_addr.s_addr, from.sin_port))) { log(LOG_DEBUG, "%s(%d)\n", __FUNCTION__,__LINE__); if ((c = get_tunnel (tunnel, from.sin_addr.s_addr, from.sin_port))) { /* * It is theoretically possible that we could be sent * a control message (say a StopCCN) on a call that we * have already closed or some such nonsense. To prevent * this from closing the tunnel, if we get a call on a valid * tunnel, but not with a valid CID, we'll just send a ZLB * to ack receiving the packet. */ if (gconfig.debug_tunnel) log (LOG_DEBUG, "%s: no such call %d on tunnel %d. Sending special ZLB\n", __FUNCTION__); handle_special (buf, c, call); } else log (LOG_DEBUG, "%s: unable to find call or tunnel to handle packet. call = %d, tunnel = %d Dumping.\n", __FUNCTION__, call, tunnel); } else { buf->peer = from; /* Handle the packet */ c->container->chal_us.vector = NULL; if (handle_packet (buf, c->container, c)) { if (gconfig.debug_tunnel) log (LOG_DEBUG, "%s(%d): bad packet\n", __FUNCTION__,__LINE__); }; if (c->cnu) { /* Send Zero Byte Packet */ control_zlb (buf, c->container, c); c->cnu = 0; } } } }; st = tunnels.head; while (st) { sc = st->call_head; while (sc) { if ((sc->fd >= 0) && FD_ISSET (sc->fd, &readfds)) { /* Got some payload to send */ int result; recycle_payload (buf, sc->container->peer); #ifdef DEBUG_FLOW_MORE log (LOG_DEBUG, "%s: rws = %d, pSs = %d, pLr = %d\n", __FUNCTION__, sc->rws, sc->pSs, sc->pLr); #endif /* if ((sc->rws>0) && (sc->pSs > sc->pLr + sc->rws) && !sc->rbit) { #ifdef DEBUG_FLOW log(LOG_DEBUG, "%s: throttling payload (call = %d, tunnel = %d, Lr = %d, Ss = %d, rws = %d)!\n",__FUNCTION__, sc->cid, sc->container->tid, sc->pLr, sc->pSs, sc->rws); #endif sc->throttle = -1; We unthrottle in handle_packet if we get a payload packet, valid or ZLB, but we also schedule a dethrottle in which case the R-bit will be set FIXME: Rate Adaptive timeout? tv.tv_sec = 2; tv.tv_usec = 0; sc->dethrottle = schedule(tv, dethrottle, sc); } else */ /* while ((result=read_packet(buf,sc->fd,sc->frame & SYNC_FRAMING))>0) { */ while ((result = read_packet (buf, sc->fd, SYNC_FRAMING)) > 0) { add_payload_hdr (sc->container, sc, buf); if (gconfig.packet_dump) { do_packet_dump (buf); } sc->prx = sc->data_rec_seq_num; if (sc->zlb_xmit) { deschedule (sc->zlb_xmit); sc->zlb_xmit = NULL; } sc->tx_bytes += buf->len; sc->tx_pkts++; udp_xmit (buf); recycle_payload (buf, sc->container->peer); } if (result != 0) { log (LOG_WARN, "%s: tossing read packet, error = %s (%d). Closing call.\n", __FUNCTION__, strerror (-result), -result); strcpy (sc->errormsg, strerror (-result)); sc->needclose = -1; } } sc = sc->next; } st = st->next; } } }
/* * Process an event in a driver independent way. This means dealing * with RPN, NRPN, SysEx etc that are defined for common midi applications * such as GM, GS and XG. * There modes that this module will run in are: * Generic MIDI - no interpretation at all, it will just save current values * of controllers etc. * GM - You can use all gm_ prefixed elements of chan. Controls, RPN, NRPN, * SysEx will be interpreded as defined in General Midi. * GS - You can use all gs_ prefixed elements of chan. Codes for GS will be * interpreted. * XG - You can use all xg_ prefixed elements of chan. Codes for XG will * be interpreted. */ void snd_midi_process_event(struct snd_midi_op *ops, struct snd_seq_event *ev, struct snd_midi_channel_set *chanset) { struct snd_midi_channel *chan; void *drv; int dest_channel = 0; if (ev == NULL || chanset == NULL) { pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n"); return; } if (chanset->channels == NULL) return; if (snd_seq_ev_is_channel_type(ev)) { dest_channel = ev->data.note.channel; if (dest_channel >= chanset->max_channels) { pr_debug("ALSA: seq_midi_emul: dest channel is %d, max is %d\n", dest_channel, chanset->max_channels); return; } } chan = chanset->channels + dest_channel; drv = chanset->private_data; /* EVENT_NOTE should be processed before queued */ if (ev->type == SNDRV_SEQ_EVENT_NOTE) return; /* Make sure that we don't have a note on that should really be * a note off */ if (ev->type == SNDRV_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0) ev->type = SNDRV_SEQ_EVENT_NOTEOFF; /* Make sure the note is within array range */ if (ev->type == SNDRV_SEQ_EVENT_NOTEON || ev->type == SNDRV_SEQ_EVENT_NOTEOFF || ev->type == SNDRV_SEQ_EVENT_KEYPRESS) { if (ev->data.note.note >= 128) return; } switch (ev->type) { case SNDRV_SEQ_EVENT_NOTEON: if (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON) { if (ops->note_off) ops->note_off(drv, ev->data.note.note, 0, chan); } chan->note[ev->data.note.note] = SNDRV_MIDI_NOTE_ON; if (ops->note_on) ops->note_on(drv, ev->data.note.note, ev->data.note.velocity, chan); break; case SNDRV_SEQ_EVENT_NOTEOFF: if (! (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON)) break; if (ops->note_off) note_off(ops, drv, chan, ev->data.note.note, ev->data.note.velocity); break; case SNDRV_SEQ_EVENT_KEYPRESS: if (ops->key_press) ops->key_press(drv, ev->data.note.note, ev->data.note.velocity, chan); break; case SNDRV_SEQ_EVENT_CONTROLLER: do_control(ops, drv, chanset, chan, ev->data.control.param, ev->data.control.value); break; case SNDRV_SEQ_EVENT_PGMCHANGE: chan->midi_program = ev->data.control.value; break; case SNDRV_SEQ_EVENT_PITCHBEND: chan->midi_pitchbend = ev->data.control.value; if (ops->control) ops->control(drv, MIDI_CTL_PITCHBEND, chan); break; case SNDRV_SEQ_EVENT_CHANPRESS: chan->midi_pressure = ev->data.control.value; if (ops->control) ops->control(drv, MIDI_CTL_CHAN_PRESSURE, chan); break; case SNDRV_SEQ_EVENT_CONTROL14: /* Best guess is that this is any of the 14 bit controller values */ if (ev->data.control.param < 32) { /* set low part first */ chan->control[ev->data.control.param + 32] = ev->data.control.value & 0x7f; do_control(ops, drv, chanset, chan, ev->data.control.param, ((ev->data.control.value>>7) & 0x7f)); } else
size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) { size_t pos = 0; const char *string_start; switch(vt->parser.state) { case NORMAL: case CSI_LEADER: case CSI_ARGS: case CSI_INTERMED: case ESC: string_start = NULL; break; case STRING: case ESC_IN_STRING: string_start = bytes; break; } #define ENTER_STRING_STATE(st) do { vt->parser.state = STRING; string_start = bytes + pos + 1; } while(0) #define ENTER_STATE(st) do { vt->parser.state = st; string_start = NULL; } while(0) #define ENTER_NORMAL_STATE() ENTER_STATE(NORMAL) for( ; pos < len; pos++) { unsigned char c = bytes[pos]; if(c == 0x00 || c == 0x7f) { // NUL, DEL if(vt->parser.state >= STRING) { more_string(vt, string_start, bytes + pos - string_start); string_start = bytes + pos + 1; } continue; } if(c == 0x18 || c == 0x1a) { // CAN, SUB ENTER_NORMAL_STATE(); continue; } else if(c == 0x1b) { // ESC vt->parser.intermedlen = 0; if(vt->parser.state == STRING) vt->parser.state = ESC_IN_STRING; else ENTER_STATE(ESC); continue; } else if(c == 0x07 && // BEL, can stand for ST in OSC or DCS state vt->parser.state == STRING) { // fallthrough } else if(c < 0x20) { // other C0 if(vt->parser.state >= STRING) more_string(vt, string_start, bytes + pos - string_start); do_control(vt, c); if(vt->parser.state >= STRING) string_start = bytes + pos + 1; continue; } // else fallthrough switch(vt->parser.state) { case ESC_IN_STRING: if(c == 0x5c) { // ST vt->parser.state = STRING; done_string(vt, string_start, bytes + pos - string_start - 1); ENTER_NORMAL_STATE(); break; } vt->parser.state = ESC; // else fallthrough case ESC: switch(c) { case 0x50: // DCS start_string(vt, VTERM_PARSER_DCS); ENTER_STRING_STATE(); break; case 0x5b: // CSI vt->parser.csi_leaderlen = 0; ENTER_STATE(CSI_LEADER); break; case 0x5d: // OSC start_string(vt, VTERM_PARSER_OSC); ENTER_STRING_STATE(); break; default: if(is_intermed(c)) { if(vt->parser.intermedlen < INTERMED_MAX-1) vt->parser.intermed[vt->parser.intermedlen++] = c; } else if(!vt->parser.intermedlen && c >= 0x40 && c < 0x60) { do_control(vt, c + 0x40); ENTER_NORMAL_STATE(); } else if(c >= 0x30 && c < 0x7f) { do_escape(vt, c); ENTER_NORMAL_STATE(); } else { DEBUG_LOG("TODO: Unhandled byte %02x in Escape\n", c); } } break; case CSI_LEADER: /* Extract leader bytes 0x3c to 0x3f */ if(c >= 0x3c && c <= 0x3f) { if(vt->parser.csi_leaderlen < CSI_LEADER_MAX-1) vt->parser.csi_leader[vt->parser.csi_leaderlen++] = c; break; } /* else fallthrough */ vt->parser.csi_leader[vt->parser.csi_leaderlen] = 0; vt->parser.csi_argi = 0; vt->parser.csi_args[0] = CSI_ARG_MISSING; vt->parser.state = CSI_ARGS; /* fallthrough */ case CSI_ARGS: /* Numerical value of argument */ if(c >= '0' && c <= '9') { if(vt->parser.csi_args[vt->parser.csi_argi] == CSI_ARG_MISSING) vt->parser.csi_args[vt->parser.csi_argi] = 0; vt->parser.csi_args[vt->parser.csi_argi] *= 10; vt->parser.csi_args[vt->parser.csi_argi] += c - '0'; break; } if(c == ':') { vt->parser.csi_args[vt->parser.csi_argi] |= CSI_ARG_FLAG_MORE; c = ';'; } if(c == ';') { vt->parser.csi_argi++; vt->parser.csi_args[vt->parser.csi_argi] = CSI_ARG_MISSING; break; } /* else fallthrough */ vt->parser.csi_argi++; vt->parser.intermedlen = 0; vt->parser.state = CSI_INTERMED; case CSI_INTERMED: if(is_intermed(c)) { if(vt->parser.intermedlen < INTERMED_MAX-1) vt->parser.intermed[vt->parser.intermedlen++] = c; break; } else if(c == 0x1b) { /* ESC in CSI cancels */ } else if(c >= 0x40 && c <= 0x7e) { vt->parser.intermed[vt->parser.intermedlen] = 0; do_csi(vt, c); } /* else was invalid CSI */ ENTER_NORMAL_STATE(); break; case STRING: if(c == 0x07 || (c == 0x9c && !vt->mode.utf8)) { done_string(vt, string_start, bytes + pos - string_start); ENTER_NORMAL_STATE(); } break; case NORMAL: if(c >= 0x80 && c < 0xa0 && !vt->mode.utf8) { switch(c) { case 0x90: // DCS start_string(vt, VTERM_PARSER_DCS); ENTER_STRING_STATE(); break; case 0x9b: // CSI ENTER_STATE(CSI_LEADER); break; case 0x9d: // OSC start_string(vt, VTERM_PARSER_OSC); ENTER_STRING_STATE(); break; default: do_control(vt, c); break; } } else { size_t eaten = 0; if(vt->parser.callbacks && vt->parser.callbacks->text) eaten = (*vt->parser.callbacks->text)(bytes + pos, len - pos, vt->parser.cbdata); if(!eaten) { DEBUG_LOG("libvterm: Text callback did not consume any input\n"); /* force it to make progress */ eaten = 1; } pos += (eaten - 1); // we'll ++ it again in a moment } break; } } return len; }
void vterm_push_bytes(VTerm *vt, const char *bytes, size_t len) { size_t pos = 0; const char *string_start; switch(vt->parser_state) { case NORMAL: string_start = NULL; break; case ESC: case ESC_IN_OSC: case ESC_IN_DCS: case CSI: case OSC: case DCS: string_start = bytes; break; } #define ENTER_STRING_STATE(st) do { vt->parser_state = st; string_start = bytes + pos + 1; } while(0) #define ENTER_NORMAL_STATE() do { vt->parser_state = NORMAL; string_start = NULL; } while(0) for( ; pos < len; pos++) { unsigned char c = bytes[pos]; if(c == 0x00 || c == 0x7f) { // NUL, DEL if(vt->parser_state != NORMAL) { append_strbuffer(vt, string_start, bytes + pos - string_start); string_start = bytes + pos + 1; } continue; } if(c == 0x18 || c == 0x1a) { // CAN, SUB ENTER_NORMAL_STATE(); continue; } else if(c == 0x1b) { // ESC if(vt->parser_state == OSC) vt->parser_state = ESC_IN_OSC; else if(vt->parser_state == DCS) vt->parser_state = ESC_IN_DCS; else ENTER_STRING_STATE(ESC); continue; } else if(c == 0x07 && // BEL, can stand for ST in OSC or DCS state (vt->parser_state == OSC || vt->parser_state == DCS)) { // fallthrough } else if(c < 0x20) { // other C0 if(vt->parser_state != NORMAL) append_strbuffer(vt, string_start, bytes + pos - string_start); do_control(vt, c); if(vt->parser_state != NORMAL) string_start = bytes + pos + 1; continue; } // else fallthrough switch(vt->parser_state) { case ESC_IN_OSC: case ESC_IN_DCS: if(c == 0x5c) { // ST switch(vt->parser_state) { case ESC_IN_OSC: vt->parser_state = OSC; break; case ESC_IN_DCS: vt->parser_state = DCS; break; default: break; } do_string(vt, string_start, bytes + pos - string_start - 1); ENTER_NORMAL_STATE(); break; } vt->parser_state = ESC; string_start = bytes + pos; // else fallthrough case ESC: switch(c) { case 0x50: // DCS ENTER_STRING_STATE(DCS); break; case 0x5b: // CSI ENTER_STRING_STATE(CSI); break; case 0x5d: // OSC ENTER_STRING_STATE(OSC); break; default: if(c >= 0x30 && c < 0x7f) { /* +1 to pos because we want to include this command byte as well */ do_string(vt, string_start, bytes + pos - string_start + 1); ENTER_NORMAL_STATE(); } else if(c >= 0x20 && c < 0x30) { /* intermediate byte */ } else { fprintf(stderr, "TODO: Unhandled byte %02x in Escape\n", c); } } break; case CSI: if(c >= 0x40 && c <= 0x7f) { /* +1 to pos because we want to include this command byte as well */ do_string(vt, string_start, bytes + pos - string_start + 1); ENTER_NORMAL_STATE(); } break; case OSC: case DCS: if(c == 0x07 || (c == 0x9c && !vt->is_utf8)) { do_string(vt, string_start, bytes + pos - string_start); ENTER_NORMAL_STATE(); } break; case NORMAL: if(c >= 0x80 && c < 0xa0 && !vt->is_utf8) { switch(c) { case 0x90: // DCS ENTER_STRING_STATE(DCS); break; case 0x9b: // CSI ENTER_STRING_STATE(CSI); break; case 0x9d: // OSC ENTER_STRING_STATE(OSC); break; default: do_control(vt, c); break; } } else { size_t text_eaten = do_string(vt, bytes + pos, len - pos); if(text_eaten == 0) { string_start = bytes + pos; goto pause; } pos += (text_eaten - 1); // we'll ++ it again in a moment } break; } } pause: if(string_start && string_start < len + bytes) { size_t remaining = len - (string_start - bytes); append_strbuffer(vt, string_start, remaining); } }
static size_t do_string(VTerm *vt, const char *str_frag, size_t len) { if(vt->strbuffer_cur) { if(str_frag) append_strbuffer(vt, str_frag, len); str_frag = vt->strbuffer; len = vt->strbuffer_cur; } else if(!str_frag) { fprintf(stderr, "parser.c: TODO: No strbuffer _and_ no final fragment???\n"); len = 0; } vt->strbuffer_cur = 0; size_t eaten; switch(vt->parser_state) { case NORMAL: if(vt->parser_callbacks && vt->parser_callbacks->text) { if((eaten = (*vt->parser_callbacks->text)(str_frag, len, vt->cbdata))) { // This is /REALLY/ inconsistant if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->text) { (*vt->parser_backup_callbacks->text)(str_frag, eaten, vt->cbdata); } return eaten; } } fprintf(stderr, "libvterm: Unhandled text (%zu chars)\n", len); return 0; case ESC: if(len == 1 && str_frag[0] >= 0x40 && str_frag[0] < 0x60) { // C1 emulations using 7bit clean // ESC 0x40 == 0x80 do_control(vt, str_frag[0] + 0x40); return 0; } if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->escape) (*vt->parser_backup_callbacks->escape)(str_frag, len, vt->cbdata); if(vt->parser_callbacks && vt->parser_callbacks->escape) if((*vt->parser_callbacks->escape)(str_frag, len, vt->cbdata)) return 0; fprintf(stderr, "libvterm: Unhandled escape ESC 0x%02x\n", str_frag[len-1]); return 0; case CSI: do_string_csi(vt, str_frag, len - 1, str_frag[len - 1]); return 0; case OSC: if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->osc) (*vt->parser_backup_callbacks->osc)(str_frag, len, vt->cbdata); if(vt->parser_callbacks && vt->parser_callbacks->osc) if((*vt->parser_callbacks->osc)(str_frag, len, vt->cbdata)) return 0; fprintf(stderr, "libvterm: Unhandled OSC %.*s\n", (int)len, str_frag); return 0; case DCS: if(vt->parser_callbacks && vt->parser_callbacks->dcs) if((*vt->parser_callbacks->dcs)(str_frag, len, vt->cbdata)) return 0; if(vt->parser_backup_callbacks && vt->parser_backup_callbacks->dcs) if((*vt->parser_backup_callbacks->dcs)(str_frag, len, vt->cbdata)) return 0; fprintf(stderr, "libvterm: Unhandled DCS %.*s\n", (int)len, str_frag); return 0; case ESC_IN_OSC: case ESC_IN_DCS: fprintf(stderr, "libvterm: ARGH! Should never do_string() in ESC_IN_{OSC,DCS}\n"); return 0; } return 0; }
void network_thread () { /* * We loop forever waiting on either data from the ppp drivers or from * our network socket. Control handling is no longer done here. */ int fromlen; /* Length of the address */ int tunnel, call; /* Tunnel and call */ int recvsize; /* Length of data received */ struct buffer *buf; /* Payload buffer */ struct call *c, *sc; /* Call to send this off to */ struct tunnel *st; /* Tunnel */ fd_set readfds; /* Descriptors to watch for reading */ int max; /* Highest fd */ struct timeval tv; /* Timeout for select */ /* This one buffer can be recycled for everything except control packets */ buf = new_buf (MAX_RECV_SIZE); for (;;) { /* * First, let's send out any outgoing packets that are waiting on us. * xmit_udp should only * contain control packets in the unthreaded version! */ max = 0; FD_ZERO (&readfds); st = tunnels.head; while (st) { if (st->self->needclose ^ st->self->closing) { if (debug_tunnel) log (LOG_DEBUG, "%S: closing down tunnel %d\n", __FUNCTION__, st->ourtid); call_close (st->self); /* Reset the while loop and check for NULL */ st = tunnels.head; if (!st) break; continue; } sc = st->call_head; while (sc) { if (sc->needclose ^ sc->closing) { call_close (sc); sc = st->call_head; if (!sc) break; continue; } if (sc->fd > -1) { /* if (!sc->throttle && !sc->needclose && !sc->closing) { */ if (!sc->needclose && !sc->closing) { if (sc->fd > max) max = sc->fd; FD_SET (sc->fd, &readfds); } } sc = sc->next; } st = st->next; } FD_SET (server_socket, &readfds); if (server_socket > max) max = server_socket; FD_SET (control_fd, &readfds); if (control_fd > max) max = control_fd; tv.tv_sec = 1; tv.tv_usec = 0; /*add start, by MJ.*/ extern int is_first_run; if(is_first_run) { int lac_fp; /* to get conn_id which written by acos */ char cmd[64]={0}; char conn_id[64] = "c default"; lac_fp = fopen("/tmp/l2tp/l2tpd.info", "r"); if (lac_fp != NULL){ //fscanf(lac_fp, "%s", conn_id); fgets(conn_id, sizeof(conn_id), lac_fp); fclose(lac_fp); } else log (LOG_DEBUG, "open /tmp/l2tp/l2tpd.info fialed\n"); log (LOG_DEBUG, "%s: -> the first run.\n", __FUNCTION__); sprintf(cmd, "c %s", conn_id); //do_control("c MJ."); do_control(cmd); //write(control_fd, cmd, strlen(cmd) ); is_first_run = 0; } /*add end. by MJ.*/ schedule_unlock (); select (max + 1, &readfds, NULL, NULL, NULL); schedule_lock (); if (FD_ISSET (control_fd, &readfds)) { do_control (NULL); } if (FD_ISSET (server_socket, &readfds)) { /* wklin added start, 04/12/2011 */ extern void connect_pppunit(void); connect_pppunit(); /* wklin added end, 04/12/2011 */ /* * Okay, now we're ready for reading and processing new data. */ recycle_buf (buf); /* Reserve space for expanding payload packet headers */ buf->start += PAYLOAD_BUF; buf->len -= PAYLOAD_BUF; fromlen = sizeof (from); recvsize = recvfrom (server_socket, buf->start, buf->len, 0, (struct sockaddr *) &from, &fromlen); /* , by MJ. for debugging.*/ //log (LOG_DEBUG, "receive %d bytes from server_scoket.\n", recvsize); if (recvsize < MIN_PAYLOAD_HDR_LEN) { if (recvsize < 0) { if (errno != EAGAIN) log (LOG_WARN, "%s: recvfrom returned error %d (%s)\n", __FUNCTION__, errno, strerror (errno)); } else { log (LOG_WARN, "%s: received too small a packet\n", __FUNCTION__); } } else { buf->len = recvsize; fix_hdr (buf->start); extract (buf->start, &tunnel, &call); if (debug_network) { log (LOG_DEBUG, "%s: recv packet from %s, size = %d," "tunnel = %d, call = %d\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call); } if (packet_dump) { do_packet_dump (buf); } if (! (c = get_call (tunnel, call, from.sin_addr.s_addr, from.sin_port))) { if ((c = get_tunnel (tunnel, from.sin_addr.s_addr, from.sin_port))) { /* * It is theoretically possible that we could be sent * a control message (say a StopCCN) on a call that we * have already closed or some such nonsense. To prevent * this from closing the tunnel, if we get a call on a valid * tunnel, but not with a valid CID, we'll just send a ZLB * to ack receiving the packet. */ if (debug_tunnel) log (LOG_DEBUG, "%s: no such call %d on tunnel %d. Sending special ZLB\n", __FUNCTION__); handle_special (buf, c, call); } else log (LOG_DEBUG, "%s: unable to find call or tunnel to handle packet. call = %d, tunnel = %d Dumping.\n", __FUNCTION__, call, tunnel); } else { buf->peer = from; /* Handle the packet */ c->container->chal_us.vector = NULL; if (handle_packet (buf, c->container, c)) { if (debug_tunnel) log (LOG_DEBUG, "%s: bad packet\n", __FUNCTION__); }; if (c->cnu) { /* Send Zero Byte Packet */ control_zlb (buf, c->container, c); c->cnu = 0; } } } }; st = tunnels.head; while (st) { sc = st->call_head; while (sc) { if ((sc->fd >= 0) && FD_ISSET (sc->fd, &readfds)) { /* Got some payload to send */ int result; recycle_payload (buf, sc->container->peer); #ifdef DEBUG_FLOW_MORE log (LOG_DEBUG, "%s: rws = %d, pSs = %d, pLr = %d\n", __FUNCTION__, sc->rws, sc->pSs, sc->pLr); #endif /* if ((sc->rws>0) && (sc->pSs > sc->pLr + sc->rws) && !sc->rbit) { #ifdef DEBUG_FLOW log(LOG_DEBUG, "%s: throttling payload (call = %d, tunnel = %d, Lr = %d, Ss = %d, rws = %d)!\n",__FUNCTION__, sc->cid, sc->container->tid, sc->pLr, sc->pSs, sc->rws); #endif sc->throttle = -1; We unthrottle in handle_packet if we get a payload packet, valid or ZLB, but we also schedule a dethrottle in which case the R-bit will be set FIXME: Rate Adaptive timeout? tv.tv_sec = 2; tv.tv_usec = 0; sc->dethrottle = schedule(tv, dethrottle, sc); } else */ /* while ((result=read_packet(buf,sc->fd,sc->frame & SYNC_FRAMING))>0) { */ while ((result = read_packet (buf, sc->fd, SYNC_FRAMING)) > 0) { add_payload_hdr (sc->container, sc, buf); if (packet_dump) { do_packet_dump (buf); } sc->prx = sc->data_rec_seq_num; if (sc->zlb_xmit) { deschedule (sc->zlb_xmit); sc->zlb_xmit = NULL; } sc->tx_bytes += buf->len; sc->tx_pkts++; udp_xmit (buf); recycle_payload (buf, sc->container->peer); } if (result != 0) { log (LOG_WARN, "%s: tossing read packet, error = %s (%d). Closing call.\n", __FUNCTION__, strerror (-result), -result); strcpy (sc->errormsg, strerror (-result)); sc->needclose = -1; } } sc = sc->next; } st = st->next; } } }
int main(int argc, char *argv[]) { nextopt_t nopt = nextopt_INIT(argc, argv, ":hVb:gLq"); char opt; int opt_g = 0; int opt_L = 0; int flag_sticky = 0; uchar_t cmd[2] = {'\0', '\0'}; progname = nextopt_progname(&nopt); while((opt = nextopt(&nopt))){ char optc[2] = {nopt.opt_got, '\0'}; switch(opt){ case 'h': usage(); die(0); break; case 'V': version(); die(0); break; case 'b': basedir = nopt.opt_arg; break; case 'g': ++opt_g; break; case 'L': ++opt_L; break; case 'q': ++opt_q; break; case ':': fatal_usage("missing argument for option -", optc); break; case '?': if(nopt.opt_got != '?'){ fatal_usage("invalid option: -", optc); } /* else fallthrough: */ default : die_usage(); break; } } argc -= nopt.arg_ndx; argv += nopt.arg_ndx; if(!*argv){ eputs(progname, ": usage error: missing arguments"); die_usage(); } /* next argv is the control command (can be taken from first letter): */ switch(cmd[0] = *argv[0]){ case 'A': flag_sticky = +1; break; case 'X': flag_sticky = -1; break; case 'd': case 'u': case 'o': case 'p': case 'c': case 'a': case 'h': case 'i': case 'k': case 'q': case 't': case 'w': case '1': case '2': if(opt_L){ /* control command for log service: */ cmd[1] |= SVCMD_FLAG_LOG; } break; case 'D': case 'U': if(opt_L){ fatal_usage("meta-command '", *argv, "' may not be used with option -L"); } break; default: fatal_usage("unknown control command '", *argv, "'"); break; } --argc; ++argv; if(!*argv){ fatal_usage("missing argument: no service(s) specified"); } if(basedir == NULL) basedir = getenv("PERP_BASE"); if((basedir == NULL) || (basedir[0] == '\0')) basedir = "."; if(chdir(basedir) != 0){ fatal_syserr("unable to chdir() to ", basedir); } /* ** service activation/deactivation command (A or X): */ if(flag_sticky != 0){ do_sticky(flag_sticky, argv); die((errs ? 111 : 0)); } /* ** else: service control command */ /* killpg() flag: */ if(opt_g){ cmd[1] |= SVCMD_FLAG_KILLPG; } do_control(cmd, argv); die((errs ? 111 : 0)); }