/* -------------------------------------------------- void mpPlay(STRING *songName) Desc: Returns: - -------------------------------------------------- */ void mpPlay(STRING *songName) { WriteLog("[ ] Now playing: "); if(media_playing(mpHandle)) media_stop(mpHandle); if(mpCount > mpSongs - 1 || mpCount < 0) return; str_cpy(_mpSongTemp,songName); str_trunc(_mpSongTemp, str_len(EXT_MUSIC)-1 ); // because our four chars are: .ogg WriteLog(_mpSongTemp); NewLine(); str_cpy(mpSongTemp,PATH_MUSIC); str_cat(mpSongTemp,songName); str_for_num(_mpCount, mpCount); // strcpy is unnecessary here mpHandle = media_play(mpSongTemp,NULL,VOL_MUSIC); while(media_playing(mpHandle)) wait(1); mpNext(); }
static void socket_handler(struct service *sv) { size_t len = 0; int res = ioctl(sv->sockfd, FIONREAD, &len); assert(res == 0); uint8_t buffer[len]; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); res = recvfrom(sv->sockfd, buffer, len, 0, (struct sockaddr*)&addr, &addrlen); assert((res == len) && (addrlen == sizeof(addr))); if(len == 0) { WARN("Empty datagram"); return; } switch(buffer[0]) { case MESSAGE_ROUTE_REQ: { if(len < sizeof(struct msg_route)) { WARN("Route request too short"); return; } struct msg_route *request = (struct msg_route*)buffer; route_add(sv->table, sv->srcid, request->src, addr.sin_addr.s_addr, addr.sin_port); char tmp[sizeof(struct msg_route) + sizeof(struct route)]; struct route *lookup = (struct route*)(tmp + sizeof(struct msg_route)); route_lookup(sv->table, sv->srcid, request->dst, lookup); INFO("Route request from %s:%hu, have %d nodes", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), lookup->count); struct msg_route *response = (struct msg_route*)tmp; response->id = MESSAGE_ROUTE_RES; memcpy(response->src, sv->srcid, 20); memcpy(response->dst, request->dst, 20); len = lookup->count * sizeof(struct route_node) + sizeof(struct msg_route); res = sendto(sv->sockfd, response, len, 0, (struct sockaddr*)&addr, sizeof(addr)); assert(res > 0); break; } case MESSAGE_ROUTE_RES: { if(sv->state != STATE_LOOKUP) { WARN("Bad state for route response (%d)", sv->state); return; } if(len < sizeof(struct msg_route)) { WARN("Route response too short"); return; } int i; for(i = 0; i < sv->lookup.offset; i++) if((addr.sin_addr.s_addr == sv->lookup.nodes[i].addr) && (addr.sin_port == sv->lookup.nodes[i].port)) { i = 0; break; } if(i) { WARN("Address mismatch"); return; } struct msg_route *msg = (struct msg_route*)buffer; if(memcmp(msg->dst, sv->dstid, 20) != 0) { WARN("Route ID mismatch"); return; } route_add(sv->table, sv->srcid, msg->src, addr.sin_addr.s_addr, addr.sin_port); uint8_t count = (len - sizeof(struct msg_route)) / sizeof(struct route_node); if(count) route_merge(msg->nodes, count < 20 ? count : 20, sv->dstid, &sv->lookup); struct itimerspec its = { { 1, 0 }, { 1, 0 } }; int res = timerfd_settime(sv->timerfd, 0, &its, NULL); assert(res == 0); lookup_handler(sv); break; } case MESSAGE_KEY_REQ: { if(sv->state == STATE_RINGING) return; if(sv->state == STATE_IDLE) { if(!crypto_keyin(sv->crypto, buffer + 1, len - 1, sv->dstid)) { WARN("Verification failed"); return; } INFO("Ringing from %s:%hu", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); route_add(sv->table, sv->srcid, sv->dstid, addr.sin_addr.s_addr, addr.sin_port); sv->addr = addr.sin_addr.s_addr; sv->port = addr.sin_port; sv->state = STATE_RINGING; sv->state_handler(SERVICE_RING, sv->dstid, sv->state_args); } else if(sv->state == STATE_ESTABLISHED) { if((addr.sin_addr.s_addr != sv->addr) || (addr.sin_port != sv->port)) { WARN("Address mismatch"); return; } INFO("Sending keys (response), size = %d", sv->keylen); res = sendto(sv->sockfd, sv->keybuf, sv->keylen, 0, (struct sockaddr*)&addr, sizeof(addr)); assert(res > 0); } else WARN("Bad state for key request (%d)", sv->state); // STATE_LOOKUP, STATE_HANDSHAKE break; } case MESSAGE_KEY_RES: { uint8_t tmp[20]; if(sv->state != STATE_HANDSHAKE) { WARN("Bad state for key response (%d)", sv->state); return; } if((addr.sin_addr.s_addr != sv->addr) || (addr.sin_port != sv->port)) { WARN("Address mismatch"); return; } if(!crypto_keyin(sv->crypto, buffer + 1, len - 1, tmp)) { WARN("Verification failed"); return; } if(memcmp(tmp, sv->dstid, 20) != 0) { WARN("Peer ID mismatch"); return; } crypto_derive(sv->crypto); sv->state = STATE_ESTABLISHED; INFO("Connected to %s:%hu", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); media_start(sv->media); sv->seqnum_capture = sv->seqnum_playback = 0; struct itimerspec its = { { 0, 20000000 }, { 0, 20000000 } }; res = timerfd_settime(sv->timerfd, 0, &its, NULL); assert(res == 0); break; } case MESSAGE_PAYLOAD: { if(sv->state != STATE_ESTABLISHED) { DEBUG("Bad state for payload (%d)", sv->state); return; } if((addr.sin_addr.s_addr != sv->addr) || (addr.sin_port != sv->port)) { WARN("Address mismatch"); return; } if(len < sizeof(struct msg_payload)) { WARN("Payload too short"); return; } struct msg_payload *msg = (struct msg_payload*)buffer; uint32_t seqnum = ntohl(msg->seqnum); if(seqnum < sv->seqnum_playback) { WARN("Out of sequence %d < %d", seqnum, sv->seqnum_playback); return; } uint8_t tmp[len - sizeof(struct msg_payload)]; if(crypto_decipher(sv->crypto, seqnum, msg->tag, msg->data, tmp, sizeof(tmp)) == 0) { WARN("Corrupted message"); return; } if(seqnum > sv->seqnum_playback) { WARN("Packet lost"); media_push(sv->media, NULL, 0); sv->seqnum_playback = seqnum; } sv->seqnum_playback++; media_push(sv->media, tmp, sizeof(tmp)); break; } case MESSAGE_HANGUP: { if(sv->state < STATE_HANDSHAKE) { WARN("Bad state for hangup (%d)", sv->state); return; } // STATE_IDLE, STATE_LOOKUP if((addr.sin_addr.s_addr != sv->addr) || (addr.sin_port != sv->port)) { WARN("Address mismatch"); return; } struct itimerspec its = { { 0, 0 }, { 0, 0 } }; res = timerfd_settime(sv->timerfd, 0, &its, NULL); assert(res == 0); if(sv->state == STATE_ESTABLISHED) media_stop(sv->media); INFO("Disconnected by peer"); sv->state = STATE_IDLE; sv->state_handler(SERVICE_HANGUP, NULL, sv->state_args); break; } default: WARN("Unknown message id (%d) from %s:%hu, len = %d", buffer[0], inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), len); } }