/** * Broadcast a packet to all users on the provided virtual channel. Forward * -1 in the channel argument to send to all channel without discrimination. * @data: data to broadcast * @len: length of the data * @chan: physical channel to use * @channel: virtual channel to filter with */ void host_broadcast (const void *data, int len, chan_id chan, int channel) { int i = 0; for (i = 0; i < host->peerCount; i++) { if ((host->peers[i].state == ENET_PEER_STATE_CONNECTED) && (((client*)host->peers[i].data)->state != STATE_DISABLED) && (((client*)host->peers[i].data)->state != STATE_ISOLATED) && ((((client*)host->peers[i].data)->channel == channel) || (channel == -1))) { client *cli = host->peers[i].data; host_deliver(crypto_encipher(data, len, cli->pk), chan, cli->peer); } } }
static void timer_handler(struct service *sv) { uint64_t n; int res = read(sv->timerfd, &n, 8); assert(res == 8); if(n > 1) WARN("Missed %d timer ticks", n - 1); switch(sv->state) { case STATE_LOOKUP: lookup_handler(sv); break; case STATE_HANDSHAKE: DEBUG("Sending keys (timeout), size = %d", sv->keylen); struct sockaddr_in addr = { AF_INET, sv->port, { sv->addr } }; res = sendto(sv->sockfd, sv->keybuf, sv->keylen, 0, (struct sockaddr*)&addr, sizeof(addr)); assert(res > 0); break; case STATE_ESTABLISHED: { uint8_t buffer[sv->packet_size]; size_t len = media_pull(sv->media, buffer, sizeof(buffer)); uint8_t tmp[sizeof(struct msg_payload) + len]; struct msg_payload *msg = (struct msg_payload*)tmp; msg->id = MESSAGE_PAYLOAD; msg->seqnum = htonl(sv->seqnum_capture); crypto_encipher(sv->crypto, sv->seqnum_capture++, msg->tag, buffer, msg->data, len); DEBUG("Sending payload, size = %d", sizeof(tmp)); struct sockaddr_in addr = { AF_INET, sv->port, { sv->addr } }; res = sendto(sv->sockfd, tmp, sizeof(tmp), 0, (struct sockaddr*)&addr, sizeof(addr)); assert(res > 0); break; } default: // STATE_IDLE, STATE_RINGING WARN("No work for timer"); } }
/** * Search through the peers connected to the server to find ones on the * provided virtual channel. Compile those into a list with newline * delimiters for the clients to display locally as a peer list. * @channel: virtual channel to search * @return: a compiled encrypted packet */ int host_list (int channel) { int i = 0, report = 0; pack_talk temp; client *cli = NULL; ENetPacket *pack = NULL; memset(&temp, 0, sizeof(pack_talk)); temp.flag = PACK_LIST; for (i = 0; i < host->peerCount; i++) { if (host->peers[i].state == ENET_PEER_STATE_CONNECTED) { cli = host->peers[i].data; if ((cli->state == STATE_ENABLED) && (cli->channel == channel)) sprintf(temp.message + strlen(temp.message), "%s\n", cli->name); else if (cli->channel == channel) sprintf(temp.message + strlen(temp.message), "[Anonymous]\n"); } } for (i = 0; i < host->peerCount; i++) { if (host->peers[i].state == ENET_PEER_STATE_CONNECTED) { cli = host->peers[i].data; if (cli->channel == channel) { pack = crypto_encipher(&temp, sizeof(pack_talk), cli->pk); report = host_deliver(pack, CHANNEL_DATA, cli->peer); } } } return report; }
/** * Test all of the functions in the crypto module. * @return: result of testing */ int crypto_test (void) { int checkpoints = -5; /* testing keypair a */ unsigned char pka[crypto_box_PUBLICKEYBYTES] = {0}; unsigned char ska[crypto_box_SECRETKEYBYTES] = {0}; crypto_box_keypair(pka, ska); /* testing keypair b */ unsigned char pkb[crypto_box_PUBLICKEYBYTES] = {0}; unsigned char skb[crypto_box_SECRETKEYBYTES] = {0}; crypto_box_keypair(pkb, skb); /* message to test crypto with */ char message[] = "Hello"; /* test of encipher/decipher of data */ { unsigned char plain[5] = {0}; unsigned char dest[PREFIX + 5]; /* data was encrypted */ crypto_encipher_data(message, 5, pkb, ska, dest); if (memcmp((char *)dest + PREFIX, message, 5)) checkpoints += 1; /* data was decrypted */ crypto_decipher_data((char *)dest, PREFIX + 5, pka, skb, plain); if (!memcmp(plain, message, 5)) checkpoints += 1; } /* test of encipher/decipher packets */ { unsigned char plain[5] = {0}; /* give module the identity of constituent a */ memcpy(sk, ska, crypto_box_SECRETKEYBYTES); /* give server the identity of constituent b */ memcpy(servk, pkb, crypto_box_PUBLICKEYBYTES); /* data was encrypted */ ENetPacket *pack = crypto_encipher(message, 5, NULL); if (pack) if (pack->dataLength == PREFIX + 5) if (memcmp(pack->data + PREFIX, message, 5)) checkpoints += 1; /* give module the identity of constituent b */ memcpy(sk, skb, crypto_box_SECRETKEYBYTES); /* give server the identity of constituent a */ memcpy(servk, pka, crypto_box_PUBLICKEYBYTES); /* data was decrypted */ crypto_decipher(pack, plain, NULL); if (!memcmp(plain, message, 5)) checkpoints += 1; enet_packet_destroy(pack); } if (crypto_getkey()) checkpoints += 1; return checkpoints; }