Ejemplo n.º 1
0
void ListenerService::receive(DDF &in, ostream& out)
{
    if (!in.name())
        throw ListenerException("Incoming message with no destination address rejected.");
    else if (!strcmp("ping",in.name())) {
        DDF outmsg=DDF(NULL).integer(in.integer() + 1);
        DDFJanitor jan(outmsg);
        out << outmsg;
    }

    Locker locker(SPConfig::getConfig().getServiceProvider());
    Remoted* dest=lookup(in.name());
    if (!dest)
        throw ListenerException("No destination registered for incoming message addressed to ($1).",params(1,in.name()));
    
    dest->receive(in, out);
}
Ejemplo n.º 2
0
DDF XMLAttribute::marshall() const
{
    DDF ddf = Attribute::marshall();
    ddf.name("XML");
    DDF vlist = ddf.first();
    for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
        vlist.add(DDF(NULL).string(i->c_str()));
    return ddf;
}
Ejemplo n.º 3
0
void ListenerService::receive(DDF &in, ostream& out)
{
    if (!in.name())
        throw ListenerException("Incoming message with no destination address rejected.");
    else if (!strcmp("ping", in.name())) {
        DDF outmsg = DDF(nullptr).integer(in.integer() + 1);
        DDFJanitor jan(outmsg);
        out << outmsg;
        return;
    }
    else if (!strcmp("hash", in.name())) {
#ifndef SHIBSP_LITE
        const char* hashAlg = in["alg"].string();
        const char* data = in["data"].string();
        if (!hashAlg || !*hashAlg || !data || !*data)
            throw ListenerException("Hash request missing algorithm or data parameters.");
        DDF outmsg(nullptr);
        DDFJanitor jan(outmsg);
        outmsg.string(SecurityHelper::doHash(hashAlg, data, strlen(data)).c_str());
        out << outmsg;
        return;
#else
        throw ListenerException("Hash algorithms unavailable in lite build of library.");
#endif
    }

    // Two stage lookup, on the listener itself, and the SP interface.
    ServiceProvider* sp = SPConfig::getConfig().getServiceProvider();
    Locker locker(sp);
    Remoted* dest = lookup(in.name());
    if (!dest) {
        dest = sp->lookupListener(in.name());
        if (!dest)
            throw ListenerException("No destination registered for incoming message addressed to ($1).", params(1,in.name()));
    }

    dest->receive(in, out);
}
Ejemplo n.º 4
0
void Application::clearAttributeHeaders(SPRequest& request) const
{
    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
        for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
            request.clearHeader(i->first.c_str(), i->second.c_str());
        return;
    }

    m_lock->rdlock();
    if (m_unsetHeaders.empty()) {
        // No headers yet, so we have to request them from the remote half.
        m_lock->unlock();
        m_lock->wrlock();
        if (m_unsetHeaders.empty()) {
            SharedLock wrlock(m_lock, false);
            string addr=string(getId()) + "::getHeaders::Application";
            DDF out,in = DDF(addr.c_str());
            DDFJanitor jin(in),jout(out);
            out = getServiceProvider().getListenerService()->send(in);
            if (out.islist()) {
                DDF header = out.first();
                while (header.isstring()) {
                    m_unsetHeaders.push_back(pair<string,string>(header.name(),header.string()));
                    header = out.next();
                }
            }
        }
        else {
            m_lock->unlock();
        }
        m_lock->rdlock();
    }

    // Now holding read lock.
    SharedLock unsetLock(m_lock, false);
    for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
        request.clearHeader(i->first.c_str(), i->second.c_str());
}
Ejemplo n.º 5
0
int ServerThread::job()
{
    Category& log = Category::getInstance("shibd.Listener");

    bool incomingError = true;  // set false once incoming message is received
    ostringstream sink;
#ifdef WIN32
    u_long len;
#else
    uint32_t len;
#endif

    try {
        // Read the message.
        int readlength = m_listener->recv(m_sock,(char*)&len,sizeof(len));
        if (readlength == 0) {
            log.info("detected socket closure, shutting down worker thread");
            return 1;
        }
        else if (readlength != sizeof(len)) {
            log.error("error reading size of input message");
            return -1;
        }
        len = ntohl(len);
        
        int size_read;
        stringstream is;
        while (len && (size_read = m_listener->recv(m_sock, m_buf, sizeof(m_buf))) > 0) {
            is.write(m_buf, size_read);
            len -= size_read;
        }
        
        if (len) {
            log.error("error reading input message from socket");
            return -1;
        }
        
        // Unmarshall the message.
        DDF in;
        DDFJanitor jin(in);
        is >> in;

        log.debug("dispatching message (%s)", in.name() ? in.name() : "unnamed");

        incomingError = false;

        // Dispatch the message.
        m_listener->receive(in, sink);
    }
    catch (XMLToolingException& e) {
        if (incomingError)
            log.error("error processing incoming message: %s", e.what());
        DDF out=DDF("exception").string(e.toString().c_str());
        DDFJanitor jout(out);
        sink << out;
    }
    catch (exception& e) {
        if (incomingError)
            log.error("error processing incoming message: %s", e.what());
        ListenerException ex(e.what());
        DDF out=DDF("exception").string(ex.toString().c_str());
        DDFJanitor jout(out);
        sink << out;
    }
    catch (...) {
        if (incomingError)
            log.error("unexpected error processing incoming message");
        if (!m_listener->m_catchAll)
            throw;
        ListenerException ex("An unexpected error occurred while processing an incoming message.");
        DDF out=DDF("exception").string(ex.toString().c_str());
        DDFJanitor jout(out);
        sink << out;
    }
    
    // Return whatever's available.
    string response(sink.str());
    int outlen = response.length();
    len = htonl(outlen);
    if (m_listener->send(m_sock,(char*)&len,sizeof(len)) != sizeof(len)) {
        log.error("error sending output message size");
        return -1;
    }
    if (m_listener->send(m_sock,response.c_str(),outlen) != outlen) {
        log.error("error sending output message");
        return -1;
    }
    
    return 0;
}
Ejemplo n.º 6
0
DDF SocketListener::send(const DDF& in)
{
#ifdef _DEBUG
    NDC ndc("send");
#endif

    log->debug("sending message (%s)", in.name() ? in.name() : "unnamed");

    // Serialize data for transmission.
    ostringstream os;
    os << in;
    string ostr(os.str());

    // Loop on the RPC in case we lost contact the first time through
#ifdef WIN32
    u_long len;
#else
    uint32_t len;
#endif
    int retry = 1;
    SocketListener::ShibSocket sock;
    while (retry >= 0) {
        sock = m_socketpool->get();
        
        int outlen = ostr.length();
        len = htonl(outlen);
        if (send(sock,(char*)&len,sizeof(len)) != sizeof(len) || send(sock,ostr.c_str(),outlen) != outlen) {
            log_error();
            this->close(sock);
            if (retry)
                retry--;
            else
                throw ListenerException("Failure sending remoted message ($1).", params(1,in.name()));
        }
        else {
            // SUCCESS.
            retry = -1;
        }
    }

    log->debug("send completed, reading response message");

    // Read the message.
    if (recv(sock,(char*)&len,sizeof(len)) != sizeof(len)) {
        log->error("error reading size of output message");
        this->close(sock);
        throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
    }
    len = ntohl(len);
    
    char buf[16384];
    int size_read;
    stringstream is;
    while (len && (size_read = recv(sock, buf, sizeof(buf))) > 0) {
        is.write(buf, size_read);
        len -= size_read;
    }
    
    if (len) {
        log->error("error reading output message from socket");
        this->close(sock);
        throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
    }
    
    m_socketpool->put(sock);

    // Unmarshall data.
    DDF out;
    is >> out;
    
    // Check for exception to unmarshall and throw, otherwise return.
    if (out.isstring() && out.name() && !strcmp(out.name(),"exception")) {
        // Reconstitute exception object.
        DDFJanitor jout(out);
        XMLToolingException* except=NULL;
        try { 
            except=XMLToolingException::fromString(out.string());
            log->error("remoted message returned an error: %s", except->what());
        }
        catch (XMLToolingException& e) {
            log->error("caught XMLToolingException while building the XMLToolingException: %s", e.what());
            log->error("XML was: %s", out.string());
            throw ListenerException("Remote call failed with an unparsable exception.");
        }

        auto_ptr<XMLToolingException> wrapper(except);
        wrapper->raise();
    }

    return out;
}