Wip http polling - no more free sockets


#1

hi
i´m polling a server for new infos via http… after a while a get an error that says i have no more free sockets…
but how do i close one when its time is come?

in the dataHandler function i call
wip_shutdown(http_ClientTestCtx.DataChannel ,FALSE, TRUE)
at the end of the WIP_CEV_WRITE case and
wip_shutdown(http_ClientTestCtx.DataChannel ,TRUE, FALSE);
at the end of the WIP_CEV_READ case.

also i call
wip_close( ev->channel);
at the end of the WIP_CEV_PEER_CLOSE case, which should close the socket as far as i understand the documentation…


#2

Hi,

How fast you open and close those sockets and have you count the number of sockets you created?

I found below:

When a TCP session is opened and then closed using wip_close() function at a very fast rate, it is not possible to create any more socket after few iterations.

L


#3

Hi,

Also try using the finalizer function.

A finalizer is a function which is called after the channel has been completely closed and all its associated resources are freed. Finalizers are attached to channels with the WIP_COPT_FINALIZER option, either in the wip_xxxCreateOpts function, or in the wip_setOpts function

#4

okay, now im using the finalizer to start the timer… doesnt sound too bad for a try to solve the problem

but the error comes after 15 calls… and what gets into the eye is the time between each call…

out of the serverlog:

13:16:03.772
13:16:23.484
13:16:33.689
13:16:40.151
13:16:44.962
13:16:49.015
13:16:52.347
13:16:54.585
13:16:57.349
13:16:59.271
13:17:01.155
13:17:02.888
13:17:04.426 
13:17:05.944
13:17:07.502

between the first and the second are 20 seconds… betwenn 2nd and 3rd 10 seconds, between 4th and 5th and 6th 4 seconds and then round about 1.5 seonds… 1.5 seconds is fine, but what is happening in the first 3 times :question:
what is happening there? needs the timer to warm up before it works reliable? :laughing:

#define CREG_POLLING_PERIOD 20 /* in 100ms steps */
typedef struct
{
	wip_channel_t CnxChannel;           // session channel
	wip_channel_t DataChannel;          // data channel

	u32           dataLength;           // response data length

} http_ClientTestCtx_t;

http_ClientTestCtx_t http_ClientTestCtx;

static s32 http_ClientTestCreate(void);

int waiting = 0;
static bool polling(u8 id) {
	waiting++;
	if(waiting == 50){
		http_ClientTestCreate();
		waiting = 0;
	}
	adl_tmrSubscribe( FALSE, CREG_POLLING_PERIOD, ADL_TMR_TYPE_TICK, polling);

	return FALSE;
}


static void my_finalizer( void *ctx ) {
	adl_atSendResponse(ADL_AT_UNS, "\n___My Finalizer___\n");
	polling(0);
}

static void http_ClientTestDataHandler( wip_event_t *ev, void *ctx)
{
	ascii tmpbuf[256];
	ascii Ptr_OnTrace[240];
	int len, tmplen;
	s32 status;
	http_ClientTestCtx_t *pHttpClientCtx =
			(http_ClientTestCtx_t *) &http_ClientTestCtx;

	switch(ev->kind)
	{
	case WIP_CEV_OPEN:
		TRACE(( 4, "http_ClientTestDataHandler: WIP_CEV_OPEN\n" ));
		adl_atSendResponse ( ADL_AT_UNS, "http_ClientTestDataHandler: Start\r\n" );

		// ready for getting response data
		pHttpClientCtx->dataLength  = 0;

		break;

	case WIP_CEV_READ:
		TRACE(( 4, "http_ClientTestDataHandler: WIP_CEV_READ\n" ));

		// we must read all available data to trigger WIP_CEV_READ again
		tmplen = 0;
		while( (len = wip_read( ev->channel, tmpbuf, sizeof(tmpbuf)-1)) > 0) {
			tmpbuf[len] = 0;
			adl_atSendResponse ( ADL_AT_UNS, tmpbuf );
			tmplen += len;
		}
		TRACE(( 4, "http_ClientTestDataHandler: read %d bytes\n", tmplen ));
		// compute total length of response
		pHttpClientCtx->dataLength += tmplen;
		break;

	case WIP_CEV_PEER_CLOSE:
		TRACE(( 4, "http_ClientTestDataHandler: WIP_CEV_PEER_CLOSE\n" ));
		adl_atSendResponse ( ADL_AT_UNS, "\r\n_____WIP_CEV_PEER_CLOSE_____\r\n" );

		// end of data
		// show response information
		if( wip_getOpts( ev->channel,
				WIP_COPT_HTTP_STATUS_CODE, &status,
				WIP_COPT_HTTP_STATUS_REASON, tmpbuf, sizeof(tmpbuf),
				WIP_COPT_END) == OK) {
			ascii sbuf[16];
			adl_atSendResponse ( ADL_AT_UNS, "http_ClientTestDataHandler: Status=" );
			wm_sprintf( sbuf, "%d", status);
			TRACE(( 4, "http_ClientTestDataHandler: Status=%d\n", status));
			wm_sprintf(Ptr_OnTrace, "http_ClientTestDataHandler: Reason=\"%s\"\n", tmpbuf);
			TRACE((4,Ptr_OnTrace));
		}
		if( wip_getOpts( ev->channel,
				WIP_COPT_HTTP_HEADER, "content-type", tmpbuf, sizeof(tmpbuf),
				WIP_COPT_END) == OK) {
			wm_sprintf(Ptr_OnTrace, "http_ClientTestDataHandler: Content Type=\"%s\"\n", tmpbuf);
			TRACE((4,Ptr_OnTrace));
		}

		// data channel must be closed
		wip_close( ev->channel);

		break;

	case WIP_CEV_ERROR:
		TRACE(( 4, "http_ClientTestDataHandler: WIP_CEV_ERROR %d\n",
				ev->content.error.errnum));
		adl_atSendResponse ( ADL_AT_UNS, "http_ClientTestDataHandler: ERROR\r\n" );

		// connection to server broken
		wip_close( ev->channel);

		break;

	default:
		TRACE(( 4, "http_ClientTestDataHandler: unexpected event: %d\n",
				ev->kind));
		break;
	}
}


static s32 http_ClientTestCreate(void)
{
	s32 ret = 0;

	// HTTP Session creation
	// ---------------------------
	http_ClientTestCtx.CnxChannel = wip_HTTPClientCreateOpts(

			NULL,  // no handler
			NULL,  // no context

			// default headers
			WIP_COPT_HTTP_HEADER, "User-Agent", "WIPHTTP/1.0",

			WIP_COPT_END);

	if (http_ClientTestCtx.CnxChannel == NULL)
	{
		TRACE(( 1, "cannot create http session channel\n" ));
		adl_atSendResponse ( ADL_AT_UNS, "cannot create http session channel\r\n" );
		ret = -1;
	}
	else
	{
		// HTTP GET command
		// ---------------------------
		http_ClientTestCtx.DataChannel = wip_getFileOpts(

				http_ClientTestCtx.CnxChannel,  // session channel

				HTTP_STR_URL,                   // requested URL

				http_ClientTestDataHandler,     // data handler
				&http_ClientTestCtx,            // context

				WIP_COPT_FINALIZER, my_finalizer,

				// request headers
				WIP_COPT_HTTP_HEADER, "Accept",          "text/html",
				WIP_COPT_HTTP_HEADER, "Accept-Language", "fr, en",

				WIP_COPT_END);

		if (http_ClientTestCtx.DataChannel == NULL)
		{
			TRACE(( 1, "cannot create http data channel\n" ));
			adl_atSendResponse ( ADL_AT_UNS, "cannot create http data channel\r\n" );
			wip_close( http_ClientTestCtx.CnxChannel);
			ret =-1;
		}
	}

	return(ret);
}

#5

bump
how do i ensure that a socket which got opened by a http connection can be reused by the next http connection?
i dont want to restart the modul every 15 calls, cause it takes far to long till the modul is reconnected to the gsm network and the internet :smiley:

wip_close
wip_abort
wip_shutdown
clearly aren´t enough to make a polling possible :confused:


#6

if i close the bearer and open a new one, the modul restarts after 166 http-get-requests (or at least it did so 4 times in a row :frowning: )…
so that doesnt work too :unamused:


#7

I don’t have a definite answer to your question, but regarding the client some comments (perhaps outdated):

  1. Have a look at the examples, DON’T expect them to be correct!
  2. Have a good look at the documentation, especially the state diagram of the sockets.
    DON’T expect them to be complete nor accurate. Search for awneil and documentation or the like will propably help since he takes the time to report those things.
  3. DON’T expect keep-alive to work (maybe it does by now, dont know…).
  4. POST will be uploaded as chunk encoded.
  5. sockets get lost at times… bearer reset won’t help a thing. wip reset neither (at least not on old < 2011) versions. Finalizer neither.
  6. Problems can be network dependent…

That said, you should be able to request at least for a day or so, I haven’t seen it as bad as you reported (but we log 1 per min). What I do is monitor its progress. If the log fails continuesly, the modem is reset, not polite but works. Give it a minimum period to run though or the crash monitor siwi will stop running the application.

For more fancy HTTP things I created this project github.com/jhofstee/siwi2way/bl … ve_httpc.c

I do have POST support locally, but is not in the online repo.


#8

Agreed.

Ensure that your system has its own means to positively confirm that the connection is still up, intact, active, and usable.


#9

if im correct, the FREE examples (the one which is in the wip documentation and the one thats an example project in the dev studio) doesnt close the channels correctly :unamused:
just got my own “Open At Tutorial” book and well, what shall i say… using the example which is in it, the polling works…

even if the error is hidden somewhere else, this example seems to work - or at least it did so for 1 hour now. You get a request every ~1.3 seconds, which should be even “fast” enough in systems where the user is waiting to see a result on his display - like the one im doing right now

#include "adl_global.h"
#include "generated.h"
#include "wip_net.h"
#include "wip_http.h"
#include "wip_bearer.h"
#include "wm_types.h"

const u16 wm_apmCustomStackSize = 4096;

#define GPRS_APN "web.vodafone.de"
#define GPRS_LOGIN ""
#define GPRS_PASSWORD ""

#define HTTP_PORT 80

ascii * HTTP_STR_HOSTNAME = "http://asdf.qwerty";




char smsTime[19];
int befehl = 0;
char identifikation[12];

wip_bearer_t bearerHandle = NULL;
wip_channel_t httpCnxCh = NULL;
wip_channel_t httpDataCh = NULL;
adl_tmr_t *timer_ptr;
u32 timeout_period = 5;
s32 GPIO_event_handle = 0;
s32 Polling_handle;
adl_ioDefs_t gpio_Input[1] = { ADL_IO_GPIO | 21| ADL_IO_DIR_IN };
int polling = 0;


void simHandler(u8 Event);
void evh_bearer(wip_bearer_t b, s8 event, void *ctx);
void Timer_Handler(u8 id, void * ctx);
void httpDataHandlerPolling(wip_event_t *ev, void *ctx);
void ausgeUmbruch(char* text);
void bearer_start();
void evh_bearer_polling(wip_bearer_t b, s8 event, void *ctx);
void httpFinalizerPolling(void *ctx);



void ausgabe(char* text){
	adl_atSendResponse(ADL_AT_UNS, text);
}

void ausgabeUmbruch(char* text){
	ausgabe(text);
	ausgabe("\n");
}

void ausgabeZweiTexteUmbruch(char* eins, char* zwei){
	ausgabe(eins);
	ausgabe(zwei);
	ausgabe("\n");
}

void ausgabeVariable(char* Name, char* value){
	ausgabe(Name);
	ausgabe(": ");
	ausgabe(value);
	ausgabe("\n");
}

void ausgabeZahl(char* vorText, int zahl){
	char myBuf[20] ;
	sprintf(myBuf, "%i", zahl);
	ausgabeZweiTexteUmbruch(vorText, myBuf);
}

void restart_bearer(){
	ausgabeUmbruch("restarting the bearer...");
	int r = wip_bearerStop(bearerHandle);
	if(r == 0)
		ausgabeUmbruch("wip_bearerStop: ok");
	else if(r == WIP_BERR_OK_INPROGRESS)
		ausgabeUmbruch("wip_bearerStop: WIP_BERR_OK_INPROGRESS");
	else if(r == WIP_BERR_BAD_HDL)
		ausgabeUmbruch("wip_bearerStop: WIP_BERR_BAD_HDL");

}


void pollingWasntReady(u8 id, void *ctx){
	httpFinalizerPolling(NULL);
}
void httpFinalizerPolling(void *ctx){

	if(polling == 1)
		evh_bearer_polling(NULL, WIP_BEV_IP_CONNECTED, NULL);
	else{
		timer_ptr = (adl_tmr_t*)adl_tmrSubscribe(FALSE, timeout_period, ADL_TMR_TYPE_100MS, (adl_tmrHandler_t) pollingWasntReady);
		if(timer_ptr < 0)
			ausgabeUmbruch("adl_tmrSubscribe failed");
	}
}

void httpDataHandlerPolling(wip_event_t *ev, void *ctx){
	char tmpbuf[256];
	int len, tmplen, r;
	switch(ev->kind){
	case WIP_CEV_PING:
		ausgabeUmbruch("PONG :)");
		break;

	case WIP_CEV_DONE:
		break;

	case WIP_CEV_OPEN:
		break;

	case WIP_CEV_READ:
		tmplen = 0;
		while( (len = wip_read( ev->channel, tmpbuf, sizeof(tmpbuf)-1)) > 0) {
			tmpbuf[len] = 0;
			ausgabeUmbruch(tmpbuf);
			tmplen += len;
		}
		break;

	case WIP_CEV_WRITE:
		break;

	case WIP_CEV_PEER_CLOSE:
		r = wip_close(httpDataCh);
		if(r == 0){
			//ausgabeUmbruch("wip_close(httpDataCh): ok");
		}else if(r == WIP_CERR_MEMORY){
			ausgabeUmbruch("wip_close(httpDataCh): WIP_CERR_MEMORY");
		}else if(r == WIP_CERR_INVALID ){
			ausgabeUmbruch("wip_close(httpDataCh): WIP_CERR_INVALID ");
		}

		r = wip_close(httpCnxCh);
		if(r == 0){
			//ausgabeUmbruch("wip_close(httpCnxCh): ok");
		}else if(r == WIP_CERR_MEMORY){
			ausgabeUmbruch("wip_close(httpCnxCh): WIP_CERR_MEMORY");
		}else if(r == WIP_CERR_INVALID ){
			ausgabeUmbruch("wip_close(httpCnxCh): WIP_CERR_INVALID ");
		}

		break;

	case WIP_CEV_ERROR:
		ausgabeUmbruch("WIP_CEV_ERROR - RESTART OF THE BEARER");
		restart_bearer();
		break;
	}

}

void createDataChannelPolling(u8 id, void *ctx){
	httpDataCh = wip_getFileOpts(httpCnxCh, HTTP_STR_HOSTNAME, httpDataHandlerPolling,
			NULL,
			WIP_COPT_FINALIZER, httpFinalizerPolling,
			WIP_COPT_HTTP_METHOD, WIP_HTTP_METHOD_GET,
			WIP_COPT_END);

	if(httpDataCh == NULL)
		ausgabeUmbruch("wip_getFileOpts: Failure");
}

void evh_bearer_polling(wip_bearer_t b, s8 event, void *ctx){
	//ausgabeZahl("evh_bearer_polling: ", event);

	switch(event){
	case WIP_BEV_IP_CONNECTED:
		/* Start the HTTP Session */
		httpCnxCh = wip_HTTPClientCreateOpts(NULL, NULL,
				WIP_COPT_HTTP_HEADER, "User-Agent", "WIPHTTP/1.0",
				WIP_COPT_END);
		if(httpCnxCh == NULL)
			ausgabeUmbruch("evh_bearer_polling: wip_HTTPClientCreateOpts failed!");

		timer_ptr = (adl_tmr_t*)adl_tmrSubscribe(FALSE, timeout_period, ADL_TMR_TYPE_100MS, (adl_tmrHandler_t) createDataChannelPolling);
		if(timer_ptr < 0)
			ausgabeUmbruch("adl_tmrSubscribe failed");

		break;

	case WIP_BEV_CONN_FAILED: //havent seen this event yet -> untested
		ausgabeUmbruch("WIP_BEV_CONN_FAILED");
		restart_bearer();
		break;

	case WIP_BEV_STOPPED:
		ausgabeUmbruch("##WIP_BEV_STOPPED##");

		int r = wip_bearerClose(bearerHandle);
		if(r == 0)
			ausgabeUmbruch("wip_bearerClose: ok");
		else if(r == WIP_BERR_BAD_HDL )
			ausgabeUmbruch("wip_bearerClose: Invalid handle\n");
		else if(r == WIP_BERR_BAD_STATE )
			ausgabeUmbruch("wip_bearerClose: Bearer was not stopped before closing\n");

		r = wip_netExit();
		if(r == 0)
			ausgabeUmbruch("wip_netExit: okay (allways returns 0)");
		else
			ausgabeZahl("wip_netExit: ", r);

		bearer_start(evh_bearer_polling);

		break;

	case WIP_BEV_IP_DISCONNECTED:
		ausgabeUmbruch("evh_bearer_polling: IP Communication got terminated!");
		break;

	default:
		ausgabeUmbruch("evh_bearer: other event");
		break;
	}
}

void bearer_start(wip_bearerHandler_f eventHandler_Bearer){
	//ausgabeUmbruch("starting the bearer");
	s8 ret;
	/*Open the GPRS bearer*/

	ret = wip_netInit();
	if(ret == 0){
		//ausgabeUmbruch("wip_netInit: ok");
	}else
		ausgabeZahl("wip_netInit: ", ret);


	ret = wip_bearerOpen(&bearerHandle, "GPRS", eventHandler_Bearer, NULL);
	if(ret == 0){
		//ausgabeUmbruch("wip_bearerOpen: ok");
	}else if(ret == WIP_BERR_NO_DEV )
		ausgabeUmbruch("wip_bearerOpen: The device does not exist \n");
	else if(ret == WIP_BERR_ALREADY )
		ausgabeUmbruch("wip_bearerOpen: The device is already opened \n");
	else if(ret == WIP_BERR_NO_IF )
		ausgabeUmbruch("wip_bearerOpen: The network interface is not available \n");
	else if(ret == WIP_BERR_NO_HDL )
		ausgabeUmbruch("wip_bearerOpen: No free handle\n");
	else{
		char myBuf[20] ;
		sprintf(myBuf, "%i", ret);
		ausgabeZweiTexteUmbruch("wip_bearerOpen: ", myBuf);
	}


	ret = wip_bearerSetOpts(bearerHandle,
			WIP_BOPT_GPRS_APN, GPRS_APN,
			WIP_BOPT_LOGIN, GPRS_LOGIN,
			WIP_BOPT_PASSWORD, GPRS_PASSWORD,
			WIP_BOPT_END
	);
	if(ret == 0){
		//ausgabeUmbruch("wip_bearerSetOpts: ok");
	}else if(ret == WIP_BERR_BAD_HDL )
		ausgabeUmbruch("wip_bearerSetOpts: Invalid handle \n");
	else if(ret == WIP_BERR_OPTION)
		ausgabeUmbruch("wip_bearerSetOpts: Invalid option \n");
	else if(ret == WIP_BERR_PARAM)
		ausgabeUmbruch("wip_bearerSetOpts: Invalid option value \n");
	else{
		char myBuf[20] ;
		sprintf(myBuf, "%i", ret);
		ausgabeZweiTexteUmbruch("wip_bearerOpen: ", myBuf);
	}


	ret = wip_bearerStart(bearerHandle);

	if(ret == -27){
		//ausgabeUmbruch("wip_bearerStart: ok");
	}else if(ret == WIP_BERR_LINE_BUSY)
		ausgabeUmbruch("wip_bearerStart: Line busy\n");
	else if(ret == WIP_BERR_NO_ANSWER)
		ausgabeUmbruch("wip_bearerStart: No answer\n");
	else if(ret == WIP_BERR_NO_CARRIER)
		ausgabeUmbruch("wip_bearerStart: No carrier\n");
	else if(ret == WIP_BERR_NO_SIM)
		ausgabeUmbruch("wip_bearerStart: No SIM card inserted\n");
	else if(ret == WIP_BERR_PIN_NOT_READY)
		ausgabeUmbruch("wip_bearerStart: PIN code not entered\n");
	else if(ret == WIP_BERR_GPRS_FAILED)
		ausgabeUmbruch("wip_bearerStart: GPRS setup failure\n");
	else if(ret == WIP_BERR_PPP_LCP_FAILED)
		ausgabeUmbruch("wip_bearerStart: LCP negotiation failure\n");
	else if(ret == WIP_BERR_PPP_AUTH_FAILED)
		ausgabeUmbruch("wip_bearerStart: PPP authentication failure\n");
	else if(ret == WIP_BERR_PPP_IPCP_FAILED)
		ausgabeUmbruch("wip_bearerStart: IPCP negotiation failure\n");
	else if(ret == WIP_BERR_PPP_LINK_FAILED)
		ausgabeUmbruch("wip_bearerStart: PPP peer not responding to echo requests\n");
	else if(ret == WIP_BERR_PPP_TERM_REQ)
		ausgabeUmbruch("wip_bearerStart: PPP session terminated by peer\n");
	else if(ret == WIP_BERR_CALL_REFUSED)
		ausgabeUmbruch("wip_bearerStart: Incoming call refused\n");
	else if(ret == -29)
			ausgabeUmbruch("wip_bearerStart: WIP_BERR_DEV");
	else{
		char myBuf[20] ;
		sprintf(myBuf, "%i", ret);
		ausgabeZweiTexteUmbruch("wip_bearerStart: ", myBuf);
	}

}


int anz = 0;
void GPIO_event_Handler(s32 GpioHandle, adl_ioEvent_e Event, u32 Size, void *Param)
{
	//the handler gets called once after the start of the programm.... dont want to start it imedeatly
	if(anz == 0){
		anz++;
	}else{
		switch (Event)
		{
		case ADL_IO_EVENT_INPUT_CHANGED:
			if (adl_ioReadSingle(Polling_handle, &gpio_Input[0]) == 1){
				if(polling == 0){
					ausgabeUmbruch("aktivierung des Polling");
					polling = 1;
					bearer_start(evh_bearer_polling);
				}else{
					ausgabeUmbruch("Pausiere polling");
					polling = 0;
				}
			}else{
				ausgabeUmbruch("Setze polling fort");
				polling = 1;
			}
			break;
		}
	}
}

void main_task ( void )
{
	polling = 0;

	GPIO_event_handle = adl_ioEventSubscribe(GPIO_event_Handler);

	//subscribe to GPIO service with polling every 100ms for GPIO
	Polling_handle = adl_ioSubscribe(1, gpio_Input, ADL_TMR_TYPE_100MS, 1, GPIO_event_handle);

	// If both subscriptions were ok, return OK
	if ((GPIO_event_handle > 0) && (Polling_handle > 0)){
		ausgabeUmbruch("Subscribed to GPIO Events: OK");
	}else{
		ausgabeUmbruch("Subscribed to GPIO Events: FAILED\n");
	}

}

edit:
now with a working restart of the bearer :smiley:

edit 2:
for the search function :laughing:
wip_cev_error
wip_berr_dev -29