• About TV's server
  • New in version 3.20
  • New in version 3.10
  • About the source code
  • About protocols/plugins
  • TV's server API
  • Protocol Initialisation
  • Protocol binding
  • Protocol Listening and handling
  • Protocol data storage
  • Control panel
  • Multi column list
  • Time and date
  • Http protocol functions
  • Unimplemented and/or replaced functions
  • Bind protocols

    index About binding protocols
    The initialized protocols are still not active. Each protocol has its own specific task (like data transport or data processing) and therefore need to be told to work together to actually provide a useful service, this process is called "binding protocols". Binding two or more protocols together requires the name of the protocols (and optionally the type to assure the correct protocol to be selected). The passed protocols has to be in the following order: receiver protocol-manipulator protocol(s)->laborer protocol(s), another order will not be executed and return an error. It is possible to bind one receiver, zero to infinity manipulator and one to infinity laborer protocols together. The cooperation between protocols will be identified by an unique number (ListenSession) and every protocol will have their own new data storage, specific for this session. It is possible to set this data in advanced while doing the bind request (to be able to change the control panel options). Please read "Protocol data storage" for more information about data storage. All protocols that need to cooperate will be asked to initiate the listensession. The receiver protocol will be activated on a successful initialization to do it's task, more about this at "Protocol Listening and handling".

    Bind request
    A request to bind different protocols can be done by calling the function BindToProtocol. The request will be executed immediately. Be aware that you can only execute BindToProtocol if you requested control panel rights during the initialization, this be done by setting the flag PT_CONTROLPANEL when calling function SetProtocolInformation. Optionally it can set member initOptions of structure BindStruct to set control panel options.

    Binding
    The binding process of protocols will start when all the protocols for the binding request are successfully loaded into the memory. A ListenSession structure will be created, this structure contains information about the binded protocols and supplies size for the protocol's data structure (this is set by extraSize parameter in function SetProtocolInformation). The BindToProtocolCallBack function exported by the receiver protocol will be called, this gives the receiver protocol time to initialize the ListenSession. When the protocol is done initializing the ListenSession, it should call the CallNextHandleConnection function, this function will make sure the BindToProtocolCallBack function of the other binded protocols will be called.

    Unbind request
    A request to unbind a listensession can be done by a protocol with control panel rights or by a protocol who is binded to the listensession itself.The function CloseListenSession can be used to unbind a listensession.

    Bind request example
    This example will show you how to place a bind request of protocol TCP/IP and HTTP.
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "tvsserver_base.h"
    #include "tvs_redefine_api_names.h"
    
    int main() {
    	BindStruct bindToTCPIP={0};
    	BindStruct bindToHTTP={0};
    
    	//fill in the first bindToStruct with protocol "TCP/IP" 
    	bindToTCPIP.protocolName = "TCPIP";
    	bindToTCPIP.type = PT_RECEIVER;
    
    	//link this structure to the next bindTo structure
    	bindToTCPIP.next = &bindToHTTP;
    
    	//Bind the TCP/IP to HTTP by filling in the linked structure
    	bindToHTTP.protocolName = "HTTP";
    	bindToHTTP.type = PT_LABORER;
    
    	//Start the binding process
    	if(!BindToProtocol(psess, &bindToTCPIP)) {
    		//Some error came up, try to read the error code in the protocolsession and every error code in the BindStruct structures to find out what the problem is.
    	} else {
    		//Succesfully
    	}
    }
    
    Bind example
    This example will show how a protocol should handle a BindToProtocolCallBack request.
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <Winsock2.h>
    #include "tvsserver_base.h"
    #include "tvs_redefine_api_names.h"
    
    typedef struct MyTCPIPstruct{
    	SOCKET socket;
    } MyTCPIPstruct;
    
    typedef struct MyHTTPstruct{
    	char* serverPath;
    } MyHTTPstruct;
    
    ProtocolSession *http_psess;
    ProtocolSession *tcpip_psess;
    
    #define OPT_TCP_PORT 1
    #define OPT_TCP_VERSION6 2
    
    int __stdcall BindToProtocolCallBack(ProtocolSession *psess, ListenSession *lsess, int flags) {
    	ProtocolData* pdata = FindProtocolDataStruct(psess, lsess->data);
    	MyTCPIPstruct* tcpData;
    	MyHTTPstruct* httpData;
    	struct sockaddr_in bindAddr={0};
    	struct sockaddr_in6 bindAddr6={0};
    
    	//The controlpanel always saves an byte/showt/integer as long long in 64-bit
    	#ifdef _WIN64
    		long long listenPort;
    		long long useVersion6;
    	#else
    		int listenPort;
    		int useVersion6;
    	#endif
    
    	
    	int len;
    
    	if(psess==tcpip_psess) {
    		tcpData = (MyTCPIPstruct*) &pdata->data;
    
    		//Get the port this listenSession should listen to
    		len = sizeof(listenPort);
    		if(!GetPluginData(psess, lsess, (ClientSession*) 0, (char*) OPT_TCP_PORT, (char*) &listenPort, &len, GDPD_NAME_IS_INTEGER))
    			return 0; //GetPluginData failed, return an error
    
    		if(!GetPluginData(psess, lsess, (ClientSession*) 0, (char*) OPT_TCP_VERSION6, (char*) &useVersion6, &len, GDPD_NAME_IS_INTEGER))
    			return 0; //GetPluginData failed, return an error
    
    		//Init a TCP/IP v4 of v6 socket
    		if(useVersion6) {
    			//return false if the socket failed to initialate
    			tcpData->socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
    			if(tcpData->socket==INVALID_SOCKET)
    				return 0;
    
    			//bind to the port to listen to
    			bindAddr6.sin6_family = AF_INET6;
    			bindAddr6.sin6_port = htons(listenPort);
    			if(bind(tcpData->socket, (struct sockaddr*) &bindAddr6, sizeof(bindAddr6)))
    				return 0;
    		} else {
    			//return false if the socket failed to initialate
    			tcpData->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    			if(tcpData->socket==INVALID_SOCKET)
    				return 0;
    
    			//bind to the port to listen to
    			bindAddr.sin_family = AF_INET;
    			bindAddr.sin_port = htons(listenPort);
    			if(bind(tcpData->socket, (struct sockaddr*) &bindAddr, sizeof(bindAddr)))
    				return 0;
    		}
    
    		//make the socket listen to the port
    		if(listen(tcpData->socket, SOMAXCONN))
    			return 0;
    
    		//stop the socket if the other protocols in the lsess do not succees in initiating
    		if(!RequestToBindToNextProtocol(psess, lsess)) {
    			closesocket(tcpData->socket);
    			return 0;
    		}
    
    		//return true, the function succeed
    		return 1;
    	//initiate the HTTP protocol in the listen session
    	} else if(psess==http_psess) {
    		httpData = (MyHTTPstruct*) &pdata->data;
    
    		//get the length of the server path
    		len = 0;
    		GetPluginData(psess, lsess, (ClientSession*) 0, "opt1", (char*) 0, &len, 0);
    
    		//allocate memory to receive the memory path
    		httpData->serverPath = (char*) malloc(len);
    		
    		//reveice the server path
    		if(!GetPluginData(psess, lsess, (ClientSession*) 0, "opt1", httpData->serverPath, &len, 0))
    			return 0; //GetPluginData failed, return an error
    
    		//free the memory if the other Bind functions fail.
    		if(!RequestToBindToNextProtocol(psess, lsess)) {
    			free(httpData->serverPath);
    			return 0;
    		}
    		return 1;
    	}
    }
    
    CloseListenSession example
    This example will show how a protocol should handle a PrepareCloseListenSession and CloseListenSession request.
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <Winsock2.h>
    #include "tvsserver_base.h"
    #include "tvs_redefine_api_names.h"
    
    //Close the socket
    int __stdcall PrepareCloseListenSession(ProtocolSession *psess, ListenSession *lsess){
        ProtocolData* pdata = FindProtocolDataStruct(psess, lsess->data);
        MyTCPIPstruct* tcpData = (MyTCPIPstruct*) &pdata->data;
    	SOCKET mySock;
    
    	//Get socket
    	mySock = tcpData->socket;
    	//clear tcpData->socket
    	tcpData->socket = 0;
    	//Close the socket
    	closesocket(mySock);
    
    	return 1;
    }
    
    int __stdcall CloseListenSession(ProtocolSession *psess, ListenSession *lsess) {
        ProtocolData* pdata = FindProtocolDataStruct(psess, lsess->data);
        MyTCPIPstruct* tcpData = (MyTCPIPstruct*) &pdata->data;
        MyHTTPstruct* httpData = (MyHTTPstruct*) &pdata->data;
    	
    	//If protocol is TCP/IP: close the socket (if not already done)
    	if(psess==tcpip_psess) {
    		if(tcpData->socket!=0) {
    			closesocket(tcpData->socket);
    			tcpData->socket = 0;
    		}
    	//If protocol is Replay: free teh memory for the serverPath
    	} else if(psess==http_psess) {
    		if(httpData->serverPath){
    			free(httpData->serverPath);
    			httpData->serverPath=0;
    		}
    	}
    	return 1;
    }