Protocol *ProtocolManager::getServerProtocol(const ProtType_t type, const InterfaceRef& iface)
{
	Protocol *p = NULL;
	protocol_registry_t::iterator it = protocol_registry.begin();

	// For an explanation of how this function works, see getSenderProtocol

	for (; it != protocol_registry.end(); it++) {
		p = (*it).second;

		// Assume that we are only looking for a specific type of server
		// protocol, i.e., there is only one server for multiple interfaces
		// of the same type
		if (p->isServer() && type == p->getType())
			break;
		
		p = NULL;
	}

	if (p == NULL) {
		switch (type) {
#if defined(ENABLE_BLUETOOTH)
                        case Protocol::TYPE_RFCOMM:
				p = new ProtocolRFCOMMServer(iface, this);
                                break;
#endif
                        case Protocol::TYPE_TCP:
                                p = new ProtocolTCPServer(iface, this, tcpServerPort, tcpBacklog);
                                break;
                                
#if defined(ENABLE_MEDIA)
			case Protocol::TYPE_MEDIA:
				/*
                                if (!strstr(iface->getMacAddrStr(), "00:00:00:00")) {				
						p = new ProtocolMediaServer(iface, this);
        			}
				*/
				break;
#endif
		default:
			HAGGLE_DBG("Unable to create server protocol for type %ld\n", type);
			break;
		}
		
		if (p) {
			if (!p->init() || !registerProtocol(p)) {
				HAGGLE_ERR("Could not initialize or register protocol %s\n", p->getName());
				delete p;
				p = NULL;
			}
		}
	}

	return p;
}
// FIXME: seems to be unused. Delete?
Protocol *ProtocolManager::getReceiverProtocol(const ProtType_t type, const InterfaceRef& iface)
{
	Protocol *p = NULL;
	protocol_registry_t::iterator it = protocol_registry.begin();

	// For an explanation of how this function works, see getSenderProtocol
	for (; it != protocol_registry.end(); it++) {
		p = (*it).second;

		if (p->isReceiver() && type == p->getType() && p->isForInterface(iface) && !p->isGarbage() && !p->isDone()) {
			if (type == Protocol::TYPE_UDP || type == Protocol::TYPE_LOCAL)
				break;
			else if (p->isConnected())
				break;
		}

		p = NULL;
	}

	if (p == NULL) {
		switch (type) {
#if defined(ENABLE_BLUETOOTH)
                        case Protocol::TYPE_RFCOMM:
				// FIXME: write a correct version of this line:
				p = NULL;//new ProtocolRFCOMMReceiver(0, iface, RFCOMM_DEFAULT_CHANNEL, this);
			break;
#endif
                        case Protocol::TYPE_TCP:
				// FIXME: write a correct version of this line:
				p = NULL;//new ProtocolTCPReceiver(0, (struct sockaddr *) NULL, iface, this);
			break;

#if defined(ENABLE_MEDIA)
		case Protocol::TYPE_MEDIA:
			// does not apply to protocol media
			break;
#endif
		default:
			HAGGLE_DBG("Unable to create client receiver protocol for type %ld\n", type);
			break;
		}
		
		if (p) {
			if (!p->init() || !registerProtocol(p)) {
				HAGGLE_ERR("Could not initialize or register protocol %s\n", p->getName());
				delete p;
				p = NULL;
			}
		}
	}

	return p;
}
    //--------------------------------------------------------------
    bool Client::connect ( ClientOptions options ){
        ofLog( OF_LOG_VERBOSE, "[ofxLibwebsockets] connect: "+options.host+":"+ofToString(options.port)+options.channel+":"+ofToString(options.bUseSSL) );
        address = options.host;
        port    = options.port;  
        channel = options.channel;
        defaultOptions = options;
        bShouldReconnect = defaultOptions.reconnect;

		/*
			enum lws_log_levels {
			LLL_ERR = 1 << 0,
			LLL_WARN = 1 << 1,
			LLL_NOTICE = 1 << 2,
			LLL_INFO = 1 << 3,
			LLL_DEBUG = 1 << 4,
			LLL_PARSER = 1 << 5,
			LLL_HEADER = 1 << 6,
			LLL_EXT = 1 << 7,
			LLL_CLIENT = 1 << 8,
			LLL_LATENCY = 1 << 9,
			LLL_COUNT = 10 
		};
		*/
		lws_set_log_level(LLL_ERR, NULL);

        // set up default protocols
        struct libwebsocket_protocols null_protocol = { NULL, NULL, 0 };
        
        // setup the default protocol (the one that works when you do addListener())
        registerProtocol( options.protocol, clientProtocol );  
        
        lws_protocols.clear();
        for (int i=0; i<protocols.size(); ++i)
        {
            struct libwebsocket_protocols lws_protocol = {
                ( protocols[i].first == "NULL" ? NULL : protocols[i].first.c_str() ),
                lws_client_callback,
                protocols[i].second->rx_buffer_size,
                protocols[i].second->rx_buffer_size
            };
            lws_protocols.push_back(lws_protocol);
        }
        lws_protocols.push_back(null_protocol);

        struct lws_context_creation_info info;
        memset(&info, 0, sizeof info);
        info.port = CONTEXT_PORT_NO_LISTEN;
        info.protocols = &lws_protocols[0];
        info.extensions = libwebsocket_get_internal_extensions();
        info.gid = -1;
        info.uid = -1;
        
        if ( options.ka_time != 0 ){
            ofLogVerbose()<<"[ofxLibwebsockets] Setting timeout "<<options.ka_time;
            info.ka_time = options.ka_time;
            info.ka_probes = options.ka_probes;
            info.ka_interval = options.ka_interval;
        }

        context = libwebsocket_create_context(&info);

        
        //context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN, NULL,
        //                                      &lws_protocols[0], libwebsocket_internal_extensions,
        //                                      NULL, NULL, /*NULL,*/ -1, -1, 0, NULL);
        if (context == NULL){
            ofLogError() << "[ofxLibwebsockets] libwebsocket init failed";
            return false;
        } else {
            ofLogVerbose() << "[ofxLibwebsockets] libwebsocket init success";
            
            string host = options.host +":"+ ofToString( options.port );
            
            // register with or without a protocol
            if ( options.protocol == "NULL"){
                lwsconnection = libwebsocket_client_connect( context, 
                                                            options.host.c_str(), options.port, (options.bUseSSL ? 2 : 0 ),
                                                            options.channel.c_str(), host.c_str(), host.c_str(), NULL, options.version);
            } else {
                lwsconnection = libwebsocket_client_connect( context, 
                                                            options.host.c_str(), options.port, (options.bUseSSL ? 2 : 0 ), 
                                                            options.channel.c_str(), host.c_str(), host.c_str(), options.protocol.c_str(), options.version);
            }
                        
            if ( lwsconnection == NULL ){
                ofLogError() << "[ofxLibwebsockets] client connection failed";
                return false;
            } else {
                connection = new Connection( (Reactor*) &context, &clientProtocol );
                connection->ws = lwsconnection;
                
                ofLogVerbose() << "[ofxLibwebsockets] Connection successfully created. Connecting.";
                startThread();   
                return true;
            }
        }
    }
    //--------------------------------------------------------------
    bool Server::setup( ServerOptions options ){
		/*
			enum lws_log_levels {
			LLL_ERR = 1 << 0,
			LLL_WARN = 1 << 1,
			LLL_NOTICE = 1 << 2,
			LLL_INFO = 1 << 3,
			LLL_DEBUG = 1 << 4,
			LLL_PARSER = 1 << 5,
			LLL_HEADER = 1 << 6,
			LLL_EXT = 1 << 7,
			LLL_CLIENT = 1 << 8,
			LLL_LATENCY = 1 << 9,
			LLL_COUNT = 10 
		};
		*/
		lws_set_log_level(LLL_WARN, NULL);

        defaultOptions = options;
        
        port = defaultOptions.port = options.port;
        document_root = defaultOptions.documentRoot = options.documentRoot;
        
        // NULL protocol is required by LWS
        struct libwebsocket_protocols null_protocol = { NULL, NULL, 0 };
        
        //setup protocols
        lws_protocols.clear();
        
        //register main protocol
        registerProtocol( options.protocol, serverProtocol );
        
        //register any added protocols
        for (int i=0; i<protocols.size(); ++i){
            struct libwebsocket_protocols lws_protocol = {
                ( protocols[i].first == "NULL" ? NULL : protocols[i].first.c_str() ),
                lws_callback,
                protocols[i].second->rx_buffer_size,
                protocols[i].second->rx_buffer_size
            };
            lws_protocols.push_back(lws_protocol);
        }
        lws_protocols.push_back(null_protocol);
        
        // make cert paths  null if not using ssl
        const char * sslCert = NULL;
        const char * sslKey = NULL;
        
        if ( defaultOptions.bUseSSL ){
            sslCert = defaultOptions.sslCertPath.c_str();
            sslKey = defaultOptions.sslKeyPath.c_str();
        }
        
        int opts = 0;
        struct lws_context_creation_info info;
        memset(&info, 0, sizeof info);
        info.port = port;
        info.protocols = &lws_protocols[0];
        info.extensions = libwebsocket_get_internal_extensions();
        info.ssl_cert_filepath = sslCert;
        info.ssl_private_key_filepath = sslKey;
        info.gid = -1;
        info.uid = -1;
        
        if ( options.ka_time != 0 ){
            info.ka_time = options.ka_time;
            info.ka_probes = options.ka_probes;
            info.ka_interval = options.ka_interval;
        }
        
        info.options = opts;

        context = libwebsocket_create_context(&info);
        
        if (context == NULL){
            ofLogError() << "[ofxLibwebsockets] libwebsockets init failed";
            return false;
        } else {
            startThread(); // blocking, non-verbose        
            return true;
        }
    }
Protocol *ProtocolManager::getSenderProtocol(const ProtType_t type, const InterfaceRef& peerIface)
{
	Protocol *p = NULL;
	protocol_registry_t::iterator it = protocol_registry.begin();
	InterfaceRef localIface = NULL;
	InterfaceRefList ifl;

	// Go through the list of current protocols until we find one:
	for (; it != protocol_registry.end(); it++) {
		p = (*it).second;

		// Is this protocol the one we're interested in?
		if (p->isSender() && type == p->getType() && 
		    p->isForInterface(peerIface) && 
		    !p->isGarbage() && !p->isDone()) {
			break;
		}
		
		p = NULL;
	}
	
	// Did we find a protocol?
	if (p == NULL) {
		// Nope. Find a suitable local interface to associate with the protocol
		kernel->getInterfaceStore()->retrieve(PeerParentCriteria(peerIface), ifl);
		
		// Parent interface found?
		if (ifl.size() != 0) {
			// Create a new one:
			switch (type) {
#if defined(ENABLE_BLUETOOTH)
				case Protocol::TYPE_RFCOMM:
					// We always grab the first local Bluetooth interface
					p = new ProtocolRFCOMMSender(ifl.pop(), peerIface, RFCOMM_DEFAULT_CHANNEL, this);
					break;
#endif				
				case Protocol::TYPE_TCP:
					// TODO: should retrieve local interface by querying for the parent interface of the peer.
					p = new ProtocolTCPSender(ifl.pop(), peerIface, TCP_DEFAULT_PORT, this);
					break;                           
				case Protocol::TYPE_LOCAL:
					// FIXME: shouldn't be able to get here!
					HAGGLE_DBG("No local sender protocol running!\n");
					break;
				case Protocol::TYPE_UDP:
					// FIXME: shouldn't be able to get here!
					HAGGLE_DBG("No UDP sender protocol running!\n");
					break;
#if defined(ENABLE_MEDIA)
				case Protocol::TYPE_MEDIA:
					p = new ProtocolMedia(NULL, peerIface, this);
					break;
#endif
				default:
					HAGGLE_DBG("Unable to create client sender protocol for type %ld\n", type);
					break;
			}
		}
		// Were we successful?
		if (p) {
			if (!p->init() || !registerProtocol(p)) {
				HAGGLE_ERR("Could not initialize protocol %s\n", p->getName());
				delete p;
				p = NULL;
			}
		}
	}
	// Return any found or created protocol:
	return p;
}
void ProtocolManager::onAddProtocolEvent(Event *e)
{	
	registerProtocol(static_cast<Protocol *>(e->getData()));
}
/**************************************
 *  initialize protocol
 **************************************/
void init_pult_protocol_dtmf_armor(PultMessageBuilder *pBuilder)
{
    registerProtocol(PCHT_VOICECALL, &_protocol);
    pBuilder->codec->notifyDtmfDigitReceived = &process_dtmf_received;
}