view waaad/peer-in.c @ 371:e86dba02630a

Updated copyright information
author Sebastien Decugis <sdecugis@nict.go.jp>
date Mon, 25 May 2009 14:51:46 +0900
parents b9b74d6ac29e
children
line wrap: on
line source

/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2009, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

/* Peers facility.
 *
 * This file contains the code of the thread that handles messages reception of a peer.
 *
 */

#include "waaad-internal.h"
#include "peer-internal.h"	

/* The code of the p_in_th thread */
/* When this thread is created, the peer must have its p_sec_session and p_secmod already set */
static void * _peer_in_th(void * arg)
{
	_peer_t * peer = (_peer_t *)arg;
	
	THREAD_NAME_PEER( "Incoming", peer );
	TRACE_ENTRY( "%p", arg );
	
	CHECK_PARAMS_DO(VALIDATE_PEER( peer ), goto end);
	CHECK_PARAMS_DO(peer->p_secmod, goto error);
	
	/* loop until error / cancellation if using a real security module, once only otherwise */
	do {
		int ret;
		msg_t * msg;
		msg_data_t * values;
		unsigned char * buf;
		size_t buflen;
		
		/* receive next buffer from security module */
		CHECK_FCT_DO( (*peer->p_secmod->sec_recv_unprotect) ( &peer->p_sec_session, &peer->p_ext_session, (void *)&buf, &buflen ),
			{
				TRACE_DEBUG(INFO, "(The security module returned an error while receiving data)");
				goto error;
			}  );
		
		pthread_cleanup_push(cleanup_buffer, buf);
		
		TRACE_DEBUG(FULL, "Received %d bytes from peer '%s'", buflen, peer->p_diamid);
	
		/* Parse this buffer into a message */
		CHECK_FCT_DO( ret = msg_parse_buffer ( &buf, buflen, &msg ), 
			{
				log_error("Received invalid data (%d bytes) from peer '%s', data dropped. (%s)", buflen, peer->p_diamid, strerror(ret));
				free(buf);
				/* go to next message */
				continue;
			}  );
		
		pthread_cleanup_pop(0); /* cleanup buffer */
		pthread_cleanup_push(cleanup_msg, msg);
		
		/* Get the header information of the message */
		CHECK_FCT_DO(  msg_data(msg, &values),
			{
				msg_free(msg, 1);
				goto error;
			}  );
		
		/* In case this is an answer, we can proceed to some early checks */
		if ((values->msg_flags & CMD_FLAG_REQUEST) == 0) {
			uti_list_t * sent;
			msg_t * sentmsg = NULL;
			
			CHECK_POSIX_DO( pthread_mutex_lock(&peer->p_lock), goto error );
			
			/* Now search for this hop-by-hop id in the sent messages */
			for (sent = peer->p_sent.next; sent != &(peer->p_sent); sent = sent->next) {
				p_sent_t * data = (p_sent_t *) sent;
				
				if (data->hbh > values->msg_hbhid) {
					/* there is no corresponding sent message */
					break;
				}
				
				if (data->hbh == values->msg_hbhid) {
					/* we found the corresponding message, we can remove the list element */
					sentmsg = (msg_t *)(data->chain.o);
					uti_list_unlink(sent);
					free(sent);
					break;
				}
				
				/* continue to search */
			}
			
			CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_lock), goto error );
			
			if (sentmsg == NULL) {
				/* We have not sent a corresponding request; just discard the message */
				log_error("Dropped Diameter answer (hbhid '%x') from peer '%s': no matching request found.", values->msg_hbhid, peer->p_diamid);
				TRACE_DEBUG(INFO, "Message dropped");
				CHECK_FCT_DO(  msg_free(msg, 1), /* nothing */ );
				continue;
			} else {
				TRACE_DEBUG(FULL, "Found matching request, associating with answer...");
				CHECK_FCT_DO(  msg_answ_associate(msg, sentmsg), goto error );
			}
		}
		
		/* enqueue this message in the "incoming" queue of the peer */
		CHECK_FCT_DO(  meq_post( peer->p_in_q, msg ),
			{
				CHECK_FCT_DO(  msg_free(msg, 1), /* nothing */ );
				goto error;
			} );
		
		pthread_cleanup_pop(0); /* cleanup message */
	
		TRACE_DEBUG(FULL, "Received message queued in peer, sending MSGRCVD event");
		
		/* post an event "message received" */
		CHECK_FCT_DO(  _peer_events_send(peer, PEVENT_MSGRCVD, NULL), goto error  );
		
		/* loop to next received message */
	} while (peer->p_sec_hdl != NULL);
	
	goto end;

error:
	/* Signal the parent thread that we have terminated */
	CHECK_FCT_DO(  _peer_events_send(peer, PEVENT_TH_TERM_IN, NULL),  /* nothing */ );

end:	
	/* Return */
	TRACE_DEBUG (FULL, "Thread is terminated.");
	return NULL;
}

/* Start the receiver thread for a peer */
int _peer_in_start(_peer_t * peer)
{
	CHECK_PARAMS( VALIDATE_PEER(peer) );
	CHECK_PARAMS( peer->p_secmod );
	CHECK_PARAMS( peer->p_sec_session.conn );
	
	CHECK_PARAMS( peer->p_in_q );
	CHECK_PARAMS( peer->p_in_th == (pthread_t)NULL );
	
	/* Ok the peer is in appropriate state, let's start the thread */
	CHECK_POSIX(  pthread_create( &peer->p_in_th, NULL, _peer_in_th, peer )  );
	
	/* done */
	return 0;
}

/* Stop this receiving thread */
int _peer_in_stop(_peer_t * peer)
{
	CHECK_PARAMS( VALIDATE_PEER(peer) );
	
	if (peer->p_in_th != (pthread_t)NULL)
		return _thread_term(&peer->p_in_th);
	else
		return 0;
}

"Welcome to our mercurial repository"