• 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
  • Listen for and handle connections

    index About listening
    The receiver protocol will be activated when a group of protocols are successfully binded. The receiver protocol will need to wait for a client to establish a connection, this process is called "listening". When a client established a connection the receiver will need to give the control back to TV's server. An identification of the connected client can be saved in the ClientSession data storage. When the receiver protocol returns successful a new thread will be created to handle the connected client and the receiver protocol will be activated again to wait for another client to connect.

    About handling connections
    The binded protocols will be all be activated, one by one in the order they where binded, to initiate the ClientSession. Initialization can be allocating recourses, but it can also indicate sending and receiving data. When a protocol requests to receive or send data, it will call a function from TV's server. TV's server will call the protocol binded next to the requesting protocol, in reverse order. This protocol will get control and is not required to request to receive data from the next binded protocol. The requesting protocol will be activated again when the called protocol returns. When the laborer protocol is done fulfilling the clients request it should return, this will activate the other protocols who can uninitialize the Clientsession, this includes free resources and sending / receiving data from the client.

    Listen
    When the BindToProtocol function returns successful, a new thread is created calling the StartListening function from the receiver protocol. The ClientSession structure passed through the sess parameter is a copy of the ListenSession, this means the data member is identical to the data member of the ListenSession (on initialization). This function should wait for a client to connect. If a client connects successfully it should use the memory on the data member (on the ClientSession) to save any data to identify the connection to finally return the StartListening function with return value true (the size of the data member can be set by the param extraSize of the SetProtocolInformation function during the initialization of the protocol). If an error occurs this function should return false.

    Handle connection
    When the StartListening function returns successful a new thread is created calling the HandleConnection function from the receiver protocol. This gives the receiver protocol time to initialize the ClientSession (if not already done by the StartListening function). When the protocol is done initializing the ClientSession, it should call the CallNextHandleConnection function. This function will make sure the HandleConnection functions from other binded protocols will be called. When the CallNextHandleConnection function returns the protocol should clean up the mess initialized before calling this function. The HandleConnection function from the processor protocol has a different meaning and shouldn't call the CallNextHandleConnection function. It shouldn't just initialize the connection, it has start talking to the client and handle its request.

    Start listening example
    This example shows how to implement the StartListening function.
    #include <stdio.h>
    #include <stdlib.h>
    #include <Winsock2.h>
    #include "tvsserver_base.h"
    #include "tvs_redefine_api_names.h"
    
    int __stdcall StartListening(ProtocolSession *psess, ListenSession *lsess, ClientSession *sess) {
    	ProtocolData* pdata = FindProtocolDataStruct(psess, lsess->data);
    	MyTCPIPstruct* tcpData_listenSession = (MyTCPIPstruct*) &pdata->data;
    	MyTCPIPstruct* tcpData_clientsession;
    
    	pdata = FindProtocolDataStruct(psess, sess->data);
    	tcpData_clientsession = (MyTCPIPstruct*) &pdata->data;
    
    	//start listening on the socket, created by the BindToProtocol function
    	tcpData_clientsession->socket = accept(tcpData_listenSession->socket, 0, 0);
    
    	if(tcpData_clientsession->socket==INVALID_SOCKET)
    		return 0; //return false
    	else 
    		return 1;
    }
    
    Handle a connection example
    This example shows how to implement the HandleConnection function.
    #include <stdio.h>
    #include <stdlib.h>
    #include "tvsserver_base.h"
    #include "tvs_redefine_api_names.h"
    
    int __stdcall HandleConnection(ProtocolSession *psess, ClientSession *sess) {
    	char input [100];
    	int len;
    	ProtocolData* pdata = FindProtocolDataStruct(psess, sess->data);
    	MyTCPIPstruct* tcpData = (MyTCPIPstruct*) &pdata->data;;
    
    	if(psess==tcpip_psess) {
    		//call the HandleConnection function of the other binded protocols
    		CallNextHandleConnection(psess, sess);
    		//Close the socket, since we don't need it annymore
    		_CloseClientSession(psess, sess);
    		return 1;
    	} else if(psess==http_psess) {
    		len=100;
    		//receive 100 bytes (or less) and wait for a maximum time of 10 seconds
    		RecvData(psess, sess, RSF_RETURN_ON_FIRST_SUCCESSFUL_ATTEMPT, 10*1000, &input, &len);
    		//Send the data that the client just send to us received.
    		SendData(psess, sess, 0, &input, &len);
    		return 1; //we are done, return so the other protocols can close the connection
    	}
    	return 0;
    }
    
    Receive data, send data and close connection example
    This example shows how to implement the RecvData, SendData and CloseClientSession function.
    #include <stdio.h>
    #include <stdlib.h>
    #include <Winsock2.h>
    #include "tvsserver_base.h"
    #include "tvs_redefine_api_names.h"
    
    /*In this example we ignore the timeout parameter and all flags (except for RSF_PEEK_DATA) to keep the example simple*/
    int __stdcall RecvData(ProtocolSession *psess, ClientSession *sess, int flags, int timeout, char *buf, int *len) {
        ProtocolData* pdata = FindProtocolDataStruct(psess, sess->data);
        MyTCPIPstruct* tcpData = (MyTCPIPstruct*) &pdata->data;
    
    	*len = recv(tcpData->socket, buf, *len, flags&RSF_PEEK_DATA); //RSF_PEEK_DATA == MSG_PEEK
    
    	return CE_NOERR;
    }
    
    /*In this example we ignore the timeout parameter and all flags to keep the example simple*/
    int __stdcall SendData(ProtocolSession *psess, ClientSession *sess, int flags, char *buf, int *len) {
        ProtocolData* pdata = FindProtocolDataStruct(psess, sess->data);
        MyTCPIPstruct* tcpData = (MyTCPIPstruct*) &pdata->data;
    
    	*len = send(tcpData->socket, buf, *len, 0);
    
    	return CE_NOERR;
    }
    
    //Close the socket
    int __stdcall CloseClientSession(ProtocolSession *psess, ClientSession *sess){
        ProtocolData* pdata = FindProtocolDataStruct(psess, sess->data);
        MyTCPIPstruct* tcpData = (MyTCPIPstruct*) &pdata->data;
    	char myBuf[80];
    	unsigned int retv=1;
    
    	//Send message that the connection will be closed
    	shutdown(tcpData->socket,SD_SEND);
    
    	//Receive all data that is left in the buffer
    	while(retv!=0 && retv+1!=0)
    		retv = recv(tcpData->socket, (char*) &myBuf, 80, 0);
    
    	//Close the socket
    	closesocket(tcpData->socket);
    
    	return 1;
    }