void vio_link_state_change(struct vio_driver_state *vio, int event) { if (event == LDC_EVENT_UP) { vio->hs_state = VIO_HS_INVALID; switch (vio->dev_class) { case VDEV_NETWORK: case VDEV_NETWORK_SWITCH: vio->dr_state = (VIO_DR_STATE_TXREQ | VIO_DR_STATE_RXREQ); break; case VDEV_DISK: vio->dr_state = VIO_DR_STATE_TXREQ; break; case VDEV_DISK_SERVER: vio->dr_state = VIO_DR_STATE_RXREQ; break; } start_handshake(vio); } else if (event == LDC_EVENT_RESET) { vio->hs_state = VIO_HS_INVALID; if (vio->dr_state & VIO_DR_STATE_RXREG) flush_rx_dring(vio); vio->dr_state = 0x00; memset(&vio->ver, 0, sizeof(vio->ver)); ldc_disconnect(vio->lp); } }
/* Write some previously-buffered backend data upstream on the * secure socket using OpenSSL */ static void client_write(struct ev_loop *loop, ev_io *w, int revents) { (void) revents; int t; int sz; proxystate *ps = (proxystate *)w->data; assert(!ringbuffer_is_empty(&ps->ring_up)); char * next = ringbuffer_read_next(&ps->ring_up, &sz); t = SSL_write(ps->ssl, next, sz); if (t > 0) { if (t == sz) { ringbuffer_read_pop(&ps->ring_up); safe_enable_io(ps, &ps->ev_r_down); // can be re-enabled b/c we've popped if (ringbuffer_is_empty(&ps->ring_up)) { if (ps->want_shutdown) { shutdown_proxy(ps, SHUTDOWN_HARD); return; } ev_io_stop(loop, &ps->ev_w_up); } } else { ringbuffer_read_skip(&ps->ring_up, t); } } else { int err = SSL_get_error(ps->ssl, t); if (err == SSL_ERROR_WANT_READ) { start_handshake(ps, err); } else if (err == SSL_ERROR_WANT_WRITE) {} /* incomplete SSL data */ else handle_fatal_ssl_error(ps, err); } }
/* Read some data from the upstream secure socket via OpenSSL, * and buffer anything we get for writing to the backend */ static void client_read(struct ev_loop *loop, ev_io *w, int revents) { (void) revents; int t; proxystate *ps = (proxystate *)w->data; if (ps->want_shutdown) { ev_io_stop(loop, &ps->ev_r_up); return; } char * buf = ringbuffer_write_ptr(&ps->ring_down); t = SSL_read(ps->ssl, buf, RING_DATA_LEN); if (t > 0) { ringbuffer_write_append(&ps->ring_down, t); if (ringbuffer_is_full(&ps->ring_down)) ev_io_stop(loop, &ps->ev_r_up); safe_enable_io(ps, &ps->ev_w_down); } else { int err = SSL_get_error(ps->ssl, t); if (err == SSL_ERROR_WANT_WRITE) { start_handshake(ps, err); } else if (err == SSL_ERROR_WANT_READ) { } /* incomplete SSL data */ else handle_fatal_ssl_error(ps, err); } }
/* Continue/complete the asynchronous connect() before starting data transmission * between front/backend */ static void handle_connect(struct ev_loop *loop, ev_io *w, int revents) { (void) revents; int t; proxystate *ps = (proxystate *)w->data; t = connect(ps->fd_down, backaddr->ai_addr, backaddr->ai_addrlen); if (!t || errno == EISCONN || !errno) { /* INIT */ ev_io_stop(loop, &ps->ev_w_down); ev_io_init(&ps->ev_r_down, back_read, ps->fd_down, EV_READ); ev_io_init(&ps->ev_w_down, back_write, ps->fd_down, EV_WRITE); start_handshake(ps, SSL_ERROR_WANT_READ); /* for client-first handshake */ ev_io_start(loop, &ps->ev_r_down); if (OPTIONS.WRITE_IP_OCTET) { char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down); assert(ps->remote_ip.ss_family == AF_INET || ps->remote_ip.ss_family == AF_INET6); *ring_pnt++ = (unsigned char) ps->remote_ip.ss_family; if (ps->remote_ip.ss_family == AF_INET6) { memcpy(ring_pnt, &((struct sockaddr_in6 *) &ps->remote_ip) ->sin6_addr.s6_addr, 16U); ringbuffer_write_append(&ps->ring_down, 1U + 16U); } else { memcpy(ring_pnt, &((struct sockaddr_in *) &ps->remote_ip) ->sin_addr.s_addr, 4U); ringbuffer_write_append(&ps->ring_down, 1U + 4U); } ev_io_start(loop, &ps->ev_w_down); } } else if (errno == EINPROGRESS || errno == EINTR || errno == EALREADY) { /* do nothing, we'll get phoned home again... */ } else { perror("{backend-connect}"); shutdown_proxy(ps, SHUTDOWN_HARD); } }
/* Continue/complete the asynchronous connect() before starting data transmission * between front/backend */ static void handle_connect(struct ev_loop *loop, ev_io *w, int revents) { (void) revents; int t; proxystate *ps = (proxystate *)w->data; char tcp6_address_string[INET6_ADDRSTRLEN]; size_t written = 0; t = connect(ps->fd_down, backaddr->ai_addr, backaddr->ai_addrlen); if (!t || errno == EISCONN || !errno) { /* INIT */ ev_io_stop(loop, &ps->ev_w_down); ev_io_init(&ps->ev_r_down, back_read, ps->fd_down, EV_READ); ev_io_init(&ps->ev_w_down, back_write, ps->fd_down, EV_WRITE); start_handshake(ps, SSL_ERROR_WANT_READ); /* for client-first handshake */ ev_io_start(loop, &ps->ev_r_down); if (OPTIONS.WRITE_PROXY_LINE) { char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down); assert(ps->remote_ip.ss_family == AF_INET || ps->remote_ip.ss_family == AF_INET6); if(ps->remote_ip.ss_family == AF_INET) { struct sockaddr_in* addr = (struct sockaddr_in*)&ps->remote_ip; written = snprintf(ring_pnt, RING_DATA_LEN, tcp_proxy_line, "TCP4", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); } else if (ps->remote_ip.ss_family == AF_INET6) { struct sockaddr_in6* addr = (struct sockaddr_in6*)&ps->remote_ip; inet_ntop(AF_INET6,&(addr->sin6_addr),tcp6_address_string,INET6_ADDRSTRLEN); written = snprintf(ring_pnt, RING_DATA_LEN, tcp_proxy_line, "TCP6", tcp6_address_string, ntohs(addr->sin6_port)); } ringbuffer_write_append(&ps->ring_down, written); ev_io_start(loop, &ps->ev_w_down); } else if (OPTIONS.WRITE_IP_OCTET) { char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down); assert(ps->remote_ip.ss_family == AF_INET || ps->remote_ip.ss_family == AF_INET6); *ring_pnt++ = (unsigned char) ps->remote_ip.ss_family; if (ps->remote_ip.ss_family == AF_INET6) { memcpy(ring_pnt, &((struct sockaddr_in6 *) &ps->remote_ip) ->sin6_addr.s6_addr, 16U); ringbuffer_write_append(&ps->ring_down, 1U + 16U); } else { memcpy(ring_pnt, &((struct sockaddr_in *) &ps->remote_ip) ->sin_addr.s_addr, 4U); ringbuffer_write_append(&ps->ring_down, 1U + 4U); } ev_io_start(loop, &ps->ev_w_down); } } else if (errno == EINPROGRESS || errno == EINTR || errno == EALREADY) { /* do nothing, we'll get phoned home again... */ } else { perror("{backend-connect}"); shutdown_proxy(ps, SHUTDOWN_HARD); } }
void audio_data_handler(struct sk_buff *skb) { void *audio_data; struct atc_header *header; down(&handle_sem); header = (struct atc_header *)skb->data; audio_data = (u8 *) (skb->data + sizeof(struct atc_header)); pr_debug_ratelimited("cmd_code:%u, sub_cmd:%u, cmd_type:%u, len:%u\n", header->cmd_code, header->sub_cmd, header->cmd_type, header->data_len); if (header->cmd_code != AUDIO_CMD_CODE) { pr_err("Invalid cmd code: %u\n", header->cmd_code); goto out; } if (header->cmd_type != CMD_TYPE_CONFIRM && header->cmd_type != CMD_TYPE_INDICATION) { pr_err("Invalid cmd type: %u\n", header->cmd_type); goto out; } switch (header->sub_cmd) { case ATC_MSOCKET_LINKDOWN: pr_info("received MsocketLinkdown!\n"); audiostub_inited = false; wake_up_interruptible(&pcm_rxwq); wake_up_interruptible(&pcm_txwq); stop_handshake(); if (audio_fd) { filp_close(audio_fd, NULL); audio_fd = NULL; } break; case ATC_MSOCKET_LINKUP: pr_info("received MsocketLinkup!\n"); start_handshake(); break; case ATC_HANDSHAKE: { struct handshake_msg *msg = (struct handshake_msg *)audio_data; pr_info("audio_data_handler,pcm=%u, wb=%u, ver=%u\n", msg->pcm_master, msg->is_wb, msg->ver); pcm_master = msg->pcm_master > 0; pcm_wb = msg->is_wb > 0; audiostub_inited = true; stop_handshake(); break; } case ATC_VOLUMECTL: case ATC_MUTECTL: case ATC_PATHCTL: case ATC_EQCTL: case ATC_LOOPBACKCTL: case ATC_PCMRECCTL: case ATC_PCMPLAYBACKCTL: skb_queue_tail(&ctl_rxq, skb); complete(&ioctl_completion); skb = NULL; break; case ATC_PCMRECSTREAM: if (pcm_rx_opened) { pcm_rxcnt++; if (skb_queue_len(&pcm_rxq) >= MAX_AUDIO_PACKET_NUM) { pr_err_ratelimited("PCM recv overflow\n"); /* discard old packet */ kfree_skb(skb_dequeue(&pcm_rxq)); } skb_queue_tail(&pcm_rxq, skb); wake_up_interruptible(&pcm_rxwq); skb = NULL; } else pr_err("pcm rx device not opened yet\n"); break; case ATC_PCMPLAYSTREAM: if (pcm_tx_opened) { struct pcm_stream_ind *pcm_indication = (struct pcm_stream_ind *)audio_data; struct sk_buff *pcm_skb; int ret; struct pcm_stream_data *pcm_data; pcm_txcnt++; while (pcm_underrun_cnt) { pcm_skb = skb_dequeue(&pcm_txq); if (pcm_skb) { /* discard packets */ kfree_skb(pcm_skb); pcm_underrun_cnt--; } else break; } if (skb_queue_empty(&pcm_txq)) { pr_err_ratelimited("PCM send underrun\n"); pcm_underrun_cnt++; pcm_skb = alloc_empty_data(); if (!pcm_skb) break; header = (struct atc_header *)pcm_skb->data; header->cmd_code = AUDIO_CMD_CODE; header->sub_cmd = ATC_PCMPLAYSTREAM; header->cmd_type = CMD_TYPE_RESPONSE; header->data_len = sizeof(*pcm_data); pcm_data = (struct pcm_stream_data *) (pcm_skb->data + sizeof(struct atc_header)); pcm_data->msg_id = pcm_indication->msg_id; pcm_data->callback = pcm_indication->callback; pcm_data->len = pcm_pktsize; audio_tx_rawskb(pcm_skb); } else { pcm_skb = skb_dequeue(&pcm_txq); pcm_data = (struct pcm_stream_data *) (pcm_skb->data + sizeof(struct atc_header)); pcm_data->msg_id = pcm_indication->msg_id; pcm_data->callback = pcm_indication->callback; pcm_data->len = pcm_pktsize; ret = audio_tx_rawskb(pcm_skb); if (ret < 0) pr_err("PCM send error: %d\n", ret); wake_up_interruptible(&pcm_txwq); } } else pr_err("pcm tx device not opened yet\n"); break; default: pr_err("audio_data_handler,unknown:sub_cmd=%d, cmd_type=%d\n", header->sub_cmd, header->cmd_type); break; } out: kfree_skb(skb); up(&handle_sem); }