static void rx_thread(void *p1, void *p2, void *p3) { struct net_buf *buf; ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); BT_DBG("started"); while (1) { BT_DBG("rx.buf %p", rx.buf); /* We can only do the allocation if we know the initial * header, since Command Complete/Status events must use the * original command buffer (if available). */ if (rx.have_hdr && !rx.buf) { rx.buf = get_rx(K_FOREVER); BT_DBG("Got rx.buf %p", rx.buf); if (rx.remaining > net_buf_tailroom(rx.buf)) { BT_ERR("Not enough space in buffer"); rx.discard = rx.remaining; reset_rx(); } else { copy_hdr(rx.buf); } } /* Let the ISR continue receiving new packets */ uart_irq_rx_enable(h4_dev); buf = net_buf_get(&rx.fifo, K_FOREVER); do { uart_irq_rx_enable(h4_dev); BT_DBG("Calling bt_recv(%p)", buf); bt_recv(buf); /* Give other threads a chance to run if the ISR * is receiving data so fast that rx.fifo never * or very rarely goes empty. */ k_yield(); uart_irq_rx_disable(h4_dev); buf = net_buf_get(&rx.fifo, K_NO_WAIT); } while (buf); } }
static void h5_process_complete_packet(uint8_t *hdr) { struct net_buf *buf; BT_DBG(""); /* rx_ack should be in every packet */ h5.rx_ack = H5_HDR_ACK(hdr); if (reliable_packet(H5_HDR_PKT_TYPE(hdr))) { /* For reliable packet increment next transmit ack number */ h5.tx_ack = (h5.tx_ack + 1) % 8; /* Start delayed fiber to ack the packet */ h5.ack_to = fiber_delayed_start(ack_stack, sizeof(ack_stack), ack_fiber, 0, 0, 7, 0, H5_RX_ACK_TIMEOUT); } h5_print_header(hdr, "RX: >"); process_unack(); buf = h5.rx_buf; h5.rx_buf = NULL; switch (H5_HDR_PKT_TYPE(hdr)) { case HCI_3WIRE_ACK_PKT: net_buf_unref(buf); break; case HCI_3WIRE_LINK_PKT: nano_fifo_put(&h5.rx_queue, buf); break; case HCI_EVENT_PKT: case HCI_ACLDATA_PKT: hexdump("=> ", buf->data, buf->len); bt_recv(buf); break; } }
void bt_uart_isr(void *unused) { static struct bt_buf *buf; static int remaining; ARG_UNUSED(unused); while (uart_irq_update(UART) && uart_irq_is_pending(UART)) { int read; if (!uart_irq_rx_ready(UART)) { if (uart_irq_tx_ready(UART)) { BT_DBG("transmit ready\n"); } else { BT_DBG("spurious interrupt\n"); } continue; } /* Beginning of a new packet */ if (!remaining) { uint8_t type; /* Get packet type */ read = bt_uart_read(UART, &type, sizeof(type), 0); if (read != sizeof(type)) { BT_WARN("Unable to read H4 packet type\n"); continue; } switch (type) { case H4_EVT: buf = bt_uart_evt_recv(&remaining); break; case H4_ACL: buf = bt_uart_acl_recv(&remaining); break; default: BT_ERR("Unknown H4 type %u\n", type); return; } if (buf && remaining > bt_buf_tailroom(buf)) { BT_ERR("Not enough space in buffer\n"); goto failed; } BT_DBG("need to get %u bytes\n", remaining); } if (!buf) { read = bt_uart_discard(UART, remaining); BT_WARN("Discarded %d bytes\n", read); remaining -= read; continue; } read = bt_uart_read(UART, bt_buf_tail(buf), remaining, 0); buf->len += read; remaining -= read; BT_DBG("received %d bytes\n", read); if (!remaining) { BT_DBG("full packet received\n"); /* Pass buffer to the stack */ bt_recv(buf); buf = NULL; } } return; failed: bt_buf_put(buf); remaining = 0; buf = NULL; }
int bt_recv_prio(struct net_buf *buf) { return bt_recv(buf); }
static void bt_uart_isr(struct device *unused) { static struct net_buf *buf; static int remaining; ARG_UNUSED(unused); while (uart_irq_update(h4_dev) && uart_irq_is_pending(h4_dev)) { int read; if (!uart_irq_rx_ready(h4_dev)) { if (uart_irq_tx_ready(h4_dev)) { BT_DBG("transmit ready"); } else { BT_DBG("spurious interrupt"); } continue; } /* Beginning of a new packet */ if (!remaining) { uint8_t type; /* Get packet type */ read = h4_read(h4_dev, &type, sizeof(type), 0); if (read != sizeof(type)) { BT_WARN("Unable to read H4 packet type"); continue; } switch (type) { case H4_EVT: buf = h4_evt_recv(&remaining); break; case H4_ACL: buf = h4_acl_recv(&remaining); break; default: BT_ERR("Unknown H4 type %u", type); return; } BT_DBG("need to get %u bytes", remaining); if (buf && remaining > net_buf_tailroom(buf)) { BT_ERR("Not enough space in buffer"); net_buf_unref(buf); buf = NULL; } } if (!buf) { read = h4_discard(h4_dev, remaining); BT_WARN("Discarded %d bytes", read); remaining -= read; continue; } read = h4_read(h4_dev, net_buf_tail(buf), remaining, 0); buf->len += read; remaining -= read; BT_DBG("received %d bytes", read); if (!remaining) { BT_DBG("full packet received"); /* Pass buffer to the stack */ bt_recv(buf); buf = NULL; } } }
static void bt_spi_rx_thread(void) { struct net_buf *buf; u8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 }; u8_t header_slave[5]; struct bt_hci_acl_hdr acl_hdr; u8_t size; memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN); while (true) { k_sem_take(&sem_request, K_FOREVER); /* Disable IRQ pin callback to avoid spurious IRQs */ gpio_pin_disable_callback(irq_dev, GPIO_IRQ_PIN); k_sem_take(&sem_busy, K_FOREVER); do { #if defined(CONFIG_BLUETOOTH_SPI_BLUENRG) gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); gpio_pin_write(cs_dev, GPIO_CS_PIN, 0); #endif /* CONFIG_BLUETOOTH_SPI_BLUENRG */ spi_transceive(spi_dev, header_master, 5, header_slave, 5); } while (header_slave[STATUS_HEADER_TOREAD] == 0 || header_slave[STATUS_HEADER_TOREAD] == 0xFF); size = header_slave[STATUS_HEADER_TOREAD]; do { spi_transceive(spi_dev, &txmsg, size, &rxmsg, size); } while (rxmsg[0] == 0); gpio_pin_enable_callback(irq_dev, GPIO_IRQ_PIN); #if defined(CONFIG_BLUETOOTH_SPI_BLUENRG) gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); #endif /* CONFIG_BLUETOOTH_SPI_BLUENRG */ k_sem_give(&sem_busy); spi_dump_message("RX:ed", rxmsg, size); switch (rxmsg[PACKET_TYPE]) { case HCI_EVT: switch (rxmsg[EVT_HEADER_EVENT]) { case BT_HCI_EVT_VENDOR: /* Vendor events are currently unsupported */ bt_spi_handle_vendor_evt(rxmsg); continue; case BT_HCI_EVT_CMD_COMPLETE: case BT_HCI_EVT_CMD_STATUS: buf = bt_buf_get_cmd_complete(K_FOREVER); break; default: buf = bt_buf_get_rx(K_FOREVER); break; } bt_buf_set_type(buf, BT_BUF_EVT); net_buf_add_mem(buf, &rxmsg[1], rxmsg[EVT_HEADER_SIZE] + 2); break; case HCI_ACL: buf = bt_buf_get_rx(K_FOREVER); bt_buf_set_type(buf, BT_BUF_ACL_IN); memcpy(&acl_hdr, &rxmsg[1], sizeof(acl_hdr)); net_buf_add_mem(buf, &acl_hdr, sizeof(acl_hdr)); net_buf_add_mem(buf, &rxmsg[5], sys_le16_to_cpu(acl_hdr.len)); break; default: BT_ERR("Unknown BT buf type %d", rxmsg[0]); continue; } if (rxmsg[PACKET_TYPE] == HCI_EVT && bt_hci_evt_is_prio(rxmsg[EVT_HEADER_EVENT])) { bt_recv_prio(buf); } else { bt_recv(buf); } } }
void proxythread (void * client_ptr) { BT_CLIENT *client; BT_PROXY proxy = { 0 }; BT_CLIENTINFO ci = { 0 }; char buf[4096] = { 0 }; int c = 0; // set up client information client = (BT_CLIENT*) client_ptr; // welcome user if (!client->use_pass) // anon server { logevent("Accepted %s:%i", client->ip, client->port); ci.pass_reg = 1; bt_send (client->sock, ":BounceThis NOTICE :You have connected to a BounceThis server. (version " BT_VERSION_NUMBER ")\r\n" ":BounceThis NOTICE :Please type \002/BOUNCE <server> [port] [password]\002 to connect to a server.\r\n" ":BounceThis NOTICE :For a list of commands, type \002/COMMANDS\002.\r\n"); } /* parsing engine */ while (1) { char *ptr, *bufptr, *msgptr ; char msgbuf[512] = { 0 }; c = bt_recv (client->sock, buf, 4096); if (c == SOCKET_ERROR) goto abort ; buf[c] = 0; bufptr = buf; do { msgptr = msgbuf; // get first message (terminated with \r\n) while (*bufptr != '\n' && *bufptr != '\0') { if (*bufptr == 0) goto abort; *msgptr++ = *bufptr++; } *bufptr++; *msgptr = 0; ptr = strtok (msgbuf," "); if (!ptr) continue; if (!strcmpi (ptr,"PASS")) { if (ci.pass_reg) { bt_send(client->sock, ":BounceThis NOTICE :Password not needed.\r\n"); continue; } else { ptr = strtok(NULL," \r"); if (!ptr) continue; if (!strcmp (ptr, client->password)) { logevent("Accepted %s:%i", client->ip, client->port); ci.pass_reg = 1; bt_send(client->sock, ":BounceThis NOTICE :Password accepted.\r\n" ":BounceThis NOTICE :You have connected to a BounceThis server. (version " BT_VERSION_NUMBER ")\r\n" ":BounceThis NOTICE :Please type \002/BOUNCE <server> [port] [password]\002 to connect to a server.\r\n" ":BounceThis NOTICE :For a list of commands, type \002/COMMANDS\002.\r\n"); continue; } else { logevent("Refused %s (incorrect password)", client->ip); bt_send (client->sock, ":BounceThis NOTICE :Password incorrect.\r\n"); goto abort2; } } } if (ci.pass_reg) { if (!strcmpi (ptr,"COMMANDS")) { bt_send (client->sock, ":BounceThis NOTICE :Commands listing:\r\n" ":BounceThis NOTICE :\002/ABOUT\002 About BounceThis.\r\n" ":BounceThis NOTICE :\002/ADMIN\002 Login as the admin.\r\n" ":BounceThis NOTICE :\002/BOUNCE\002 Connects you to a server.\r\n" ":BounceThis NOTICE :\002/COMMANDS\002 Shows this screen.\r\n" ":BounceThis NOTICE :\002/INFO\002 Info about yourself and the server.\r\n" ":BounceThis NOTICE :\002/NICK\002 Changes your nickname.\r\n" ":BounceThis NOTICE :\002/QUIT\002 Disconnects you.\r\n"); if (ci.is_admin) bt_send (client->sock, ":BounceThis NOTICE :Admin commands listing:\r\n" ":BounceThis NOTICE :\002/BROADCAST\002 Send a message to all users.\r\n" ":BounceThis NOTICE :\002/KILL\002 Kill everyone matching an ip (BT style filters allowed)\r\n" ":BounceThis NOTICE :\002/TEMPFILTER\002 Ban everyone matching an ip (BT style filters allowed) until server is stopped.\r\n" ":BounceThis NOTICE :\002/LISTCONN\002 Lists all connections to the server.\r\n"); } else if (!strcmpi (ptr,"ABOUT")) bt_send(client->sock, ":BounceThis NOTICE :About BounceThis:\r\n" ":BounceThis NOTICE :BounceThis was created by Chris M. in 2002.\r\n" ":BounceThis NOTICE :It is a full featured Win32 BNC server designed for IRC.\r\n" ":BounceThis NOTICE :Check us out on the web at 12http://bouncethis.linear.cc\r\n"); else if (!strcmpi (ptr,"INFO")) { bt_sendf (client->sock, ":BounceThis NOTICE :" BT_VERSION ", bound on IP %s on port %i\r\n" ":BounceThis NOTICE :You are connecting as %s!%s@%s (%s)\r\n", server.ip, client->port, real(ci.nick), ci.user, client->ip, real(ci.name)); if (server.use_identd) bt_sendf (client->sock, ":BounceThis NOTICE :Identd server enabled, using ident '%s'\r\n", server.ident); } else if (!strcmpi (ptr,"NICK")) { ptr = strtok(NULL," \r"); if (!ptr) continue; bt_cpy (ci.nick, ptr); if (ci.nick_reg) bt_sendf (client->sock, ":BounceThis NOTICE :Your nickname is now \002%s\002.\r\n", real(ci.nick)); else ci.nick_reg = 1; } else if (!strcmpi (ptr,"QUIT")) goto abort; else if (!strcmpi (ptr,"USER")) { if (ci.user_reg) { bt_send (client->sock, ":BounceThis NOTICE :You cannot reregister.\r\n"); continue; } ptr = strtok(NULL," "); if (!ptr) continue; bt_cpy (ci.user, ptr); // skip next two fields. useless -_-; strtok(NULL," "); strtok(NULL," "); ptr = strtok(NULL,"\r"); if (!ptr) continue; bt_cpy (ci.name, ptr); ci.user_reg = 1; } else if (!strcmpi (ptr,"ADMIN")) { char user[16] ; char pass[16] ; ptr = strtok(NULL," \r"); if (!ptr) continue; bt_cpy(user,ptr) ; ptr = strtok(NULL," \r"); if (!ptr) continue; bt_cpy(pass,ptr) ; if (!strcmpi(user,server.admin_user) && !strcmp(pass,server.admin_pass)) { bt_send(client->sock,":BounceThis NOTICE :Admin password accepted.\r\n"); ci.is_admin = 1 ; } else { logevent("Connection from %s:%i closed (invalid admin attempt)", client->ip,client->port); bt_send (client->sock, ":BounceThis NOTICE :Admin password incorrect. Disconnecting.\r\n"); goto abort2; } } else if (!strcmpi (ptr,"BROADCAST")) { if (!ci.is_admin) // :O! { bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n"); continue ; } ptr = strtok(NULL,"\r"); if (!ptr) continue; broadcast(ptr) ; } else if (!strcmpi (ptr,"KILL")) { if (!ci.is_admin) // :O! { bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n"); continue ; } ptr = strtok(NULL,"\r"); if (!ptr) continue; bt_sendf(client->sock,":BounceThis NOTICE :Kill effected \002%i\002 users.\r\n",kill(ptr)) ; } else if (!strcmpi (ptr,"TEMPFILTER")) { if (!ci.is_admin) // :O! { bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n"); continue ; } ptr = strtok(NULL,"\r"); if (!ptr) continue; bt_sendf(client->sock,":BounceThis NOTICE :Filter effected \002%i\002 users.\r\n",tempfilter(ptr)) ; } else if (!strcmpi (ptr,"LISTCONN")) { if (!ci.is_admin) // :O! { bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n"); continue ; } list(client->sock); } else if (!strcmpi (ptr,"BOUNCE")) { ptr = strtok(NULL," \r"); if (!ptr) continue; bt_cpy (proxy.host, ptr); ptr = strtok(NULL," \r"); if (!ptr) bt_cpy(proxy.port,"6667"); else { bt_cpy (proxy.port, ptr); ptr = strtok(NULL," \r"); if (ptr) { bt_cpy (ci.pass,ptr); ci.use_pass = 1; } } proxy.sock = bt_connect (proxy.host, proxy.port); if (!proxy.sock) bt_sendf (client->sock, ":BounceThis NOTICE :Error connecting to %s:%s.\r\n", proxy.host, proxy.port); else { bt_sendf (client->sock, ":BounceThis NOTICE :Connection established to %s:%s.\r\n",proxy.host, proxy.port); if (ci.use_pass) bt_sendf (client->sock,":BounceThis NOTICE :Attempting to login with password '%s'\r\n", ci.pass); break; } } else bt_sendf (client->sock, ":BounceThis NOTICE :\002/%s\002: Invalid command.\r\n",ptr); } else { logevent("Refused %s:%i (incorrect password)", client->ip,client->port); bt_send (client->sock, ":BounceThis NOTICE :You must supply the password before performing any other commands.\r\n"); goto abort2; } } while ((char)*bufptr != (char)0) ; if (proxy.sock) /* proxy connected, break from BT IRC interface */ break; } logevent("Proxy connection to %s:%s from %s:%i", proxy.host,proxy.port, client->ip, client->port); // Register user. if (ci.use_pass) bt_sendf(proxy.sock,"PASS %s\r\n", ci.pass); bt_sendf(proxy.sock,"NICK %s\r\nUSER %s # # %s\r\n",ci.nick,ci.user,ci.name); while (1) { fd_set rset = { 0 }; FD_SET (client->sock, &rset); FD_SET (proxy.sock, &rset); if (select (0, &rset, NULL, NULL, NULL) == -1) goto abort; if (FD_ISSET (client->sock, &rset)) { c = bt_recv(client->sock, buf, 4096); if (c <= 0) goto abort; buf[c] = 0; client->sent += bt_send (proxy.sock, buf); } if (FD_ISSET (proxy.sock, &rset)) { c = bt_recv (proxy.sock, buf, 4096); if (c <= 0) goto abort; buf[c] = 0; client->recv += bt_send (client->sock, buf); } updatesrtowin(client); } abort: logevent("Connection from %s:%i closed", client->ip,client->port); abort2: // for skipping auto log. bt_close(client->sock); if (proxy.sock) { bt_close(proxy.sock); } delconn(client); _endthread(); }