/*
--------------------------------------------------
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();
	
}
示例#2
0
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);
    }
}