File: ServerListener.cpp

package info (click to toggle)
soapyremote 0.4.3-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 504 kB
  • sloc: cpp: 6,740; makefile: 13
file content (108 lines) | stat: -rw-r--r-- 2,766 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright (c) 2015-2015 Josh Blum
// SPDX-License-Identifier: BSL-1.0

#include "SoapyServer.hpp"
#include "SoapyRemoteDefs.hpp"
#include "ClientHandler.hpp"
#include "SoapyRPCSocket.hpp"
#include <thread>
#include <iostream>

/***********************************************************************
 * Server thread implementation
 **********************************************************************/
SoapyServerThreadData::SoapyServerThreadData(void):
    done(false),
    thread(nullptr),
    client(nullptr)
{
    return;
}

SoapyServerThreadData::~SoapyServerThreadData(void)
{
    done = true;
    if (thread != nullptr)
    {
        thread->join();
    }
    delete thread;
    if (client != nullptr)
    {
        std::cout << "SoapyServerListener::close()" << std::endl;
    }
    delete client;
}

void SoapyServerThreadData::handlerLoop(void)
{
    SoapyClientHandler handler(*client, uuid);

    try
    {
        while (handler.handleOnce())
        {
            if (done) break;
        }
    }
    catch (const std::exception &ex)
    {
        std::cerr << "SoapyServerListener::handlerLoop() FAIL: " << ex.what() << std::endl;
    }

    done = true;
}

/***********************************************************************
 * Socket listener constructor
 **********************************************************************/
SoapyServerListener::SoapyServerListener(SoapyRPCSocket &sock, const std::string &uuid):
    _sock(sock),
    _uuid(uuid),
    _handlerId(0)
{
    return;
}

SoapyServerListener::~SoapyServerListener(void)
{
    auto it = _handlers.begin();
    while (it != _handlers.end())
    {
        _handlers.erase(it++);
    }
}

/***********************************************************************
 * Client socket acceptor
 **********************************************************************/
void SoapyServerListener::handleOnce(void)
{
    //cleanup completed threads
    auto it = _handlers.begin();
    while (it != _handlers.end())
    {
        auto &data = it->second;
        if (not data.done) ++it;
        else _handlers.erase(it++);
    }

    //wait with timeout for the server socket to become ready to accept
    if (not _sock.selectRecv(SOAPY_REMOTE_SOCKET_TIMEOUT_US)) return;

    SoapyRPCSocket *client = _sock.accept();
    if (client == NULL)
    {
        std::cerr << "SoapyServerListener::accept() FAIL:" << _sock.lastErrorMsg() << std::endl;
        return;
    }
    std::cout << "SoapyServerListener::accept(" << client->getpeername() << ")" << std::endl;

    //setup the thread data
    auto &data = _handlers[_handlerId++];
    data.client = client;
    data.uuid = _uuid;

    //spawn a new thread
    data.thread = new std::thread(&SoapyServerThreadData::handlerLoop, &data);
}