Jelajahi Sumber

to parser fixed
timers improuved

Bogdan-Andrei Iancu 23 tahun lalu
induk
melakukan
61603aa6ae
4 mengubah file dengan 294 tambahan dan 228 penghapusan
  1. 135 62
      modules/tm/t_funcs.c
  2. 51 76
      modules/tm/timer.c
  3. 32 43
      modules/tm/timer.h
  4. 76 47
      parse_to.c

+ 135 - 62
modules/tm/t_funcs.c

@@ -12,6 +12,8 @@
 #include "../../timer.h"
 
 
+
+
 #define  append_mem_block(_d,_s,_len) \
 		do{\
 			memcpy((_d),(_s),(_len));\
@@ -26,17 +28,35 @@ struct cell         *T;
 unsigned int     global_msg_id;
 struct s_table*  hash_table;
 
+void timer_routine(unsigned int, void*);
+
+
+
+
+
+/* remove from timer list */
+inline void reset_timer( struct s_table *hash_table, struct timer_link* tl )
+{
+	/* lock(timer_group_lock[ tl->tg ]); */
+	/* hack to work arround this timer group thing*/
+	lock(hash_table->timers[timer_group[tl->tg]].mutex);
+	remove_timer_unsafe( tl );
+	unlock(hash_table->timers[timer_group[tl->tg]].mutex);
+	/*unlock(timer_group_lock[ tl->tg ]);*/
+}
+
+
 
 
 /* determine timer length and put on a correct timer list */
-inline void set_timer( struct s_table *hash_table,
-	struct timer_link *new_tl, enum lists list_id )
+inline void set_timer( struct s_table *hash_table, struct timer_link *new_tl,
+														enum lists list_id )
 {
 	unsigned int timeout;
 	struct timer* list;
-	static enum lists to_table[NR_OF_TIMER_LISTS] =
-		{	FR_TIME_OUT, INV_FR_TIME_OUT, WT_TIME_OUT, DEL_TIME_OUT,
-			RETR_T1, RETR_T1 << 1, 	RETR_T1 << 2, RETR_T2 };
+	static enum lists to_table[NR_OF_TIMER_LISTS] = {
+		FR_TIME_OUT, INV_FR_TIME_OUT, WT_TIME_OUT, DEL_TIME_OUT,
+		RETR_T1, RETR_T1 << 1, RETR_T1 << 2, RETR_T2 };
 
 	if (list_id<FR_TIMER_LIST || list_id>=NR_OF_TIMER_LISTS) {
 		LOG(L_CRIT, "ERROR: set_timer: unkown list: %d\n", list_id);
@@ -47,10 +67,7 @@ inline void set_timer( struct s_table *hash_table,
 	}
 	timeout = to_table[ list_id ];
 	list= &(hash_table->timers[ list_id ]);
-/*
-	add_to_tail_of_timer_list( &(hash_table->timers[ list_id ]),
-		new_tl,get_ticks()+timeout);
-*/
+
 	lock(list->mutex);
 	/* make sure I'm not already on a list */
 	remove_timer_unsafe( new_tl );
@@ -58,20 +75,11 @@ inline void set_timer( struct s_table *hash_table,
 	unlock(list->mutex);
 }
 
-/* remove from timer list */
-inline void reset_timer( struct s_table *hash_table,
-	struct timer_link* tl )
-{
-	/* lock(timer_group_lock[ tl->tg ]); */
-	/* hack to work arround this timer group thing*/
-	lock(hash_table->timers[timer_group[tl->tg]].mutex);
-	remove_timer_unsafe( tl );
-	unlock(hash_table->timers[timer_group[tl->tg]].mutex);
-	/*unlock(timer_group_lock[ tl->tg ]);*/
-}
+
+
 
 static inline void reset_retr_timers( struct s_table *h_table,
-	struct cell *p_cell )
+													struct cell *p_cell )
 {
 	int ijk;
 	struct retrans_buff *rb;
@@ -81,51 +89,51 @@ static inline void reset_retr_timers( struct s_table *h_table,
 	lock(hash_table->timers[RT_T1_TO_1].mutex);
 	remove_timer_unsafe( & p_cell->outbound_response.retr_timer );
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  {
-			if ( rb = p_cell->outbound_request[ijk] ) {
-				remove_timer_unsafe( & rb->retr_timer );
-			}
+		if ( rb = p_cell->outbound_request[ijk] ) {
+			remove_timer_unsafe( & rb->retr_timer );
 		}
+	}
 	unlock(hash_table->timers[RT_T1_TO_1].mutex);
 
 	lock(hash_table->timers[FR_TIMER_LIST].mutex);
 	remove_timer_unsafe( & p_cell->outbound_response.fr_timer );
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  {
-			if ( rb = p_cell->outbound_request[ijk] ) {
-				remove_timer_unsafe( & rb->fr_timer );
-			}
+		if ( rb = p_cell->outbound_request[ijk] ) {
+			remove_timer_unsafe( & rb->fr_timer );
 		}
+	}
 	unlock(hash_table->timers[FR_TIMER_LIST].mutex);
 	DBG("DEBUG:stop_RETR_and_FR_timers : timers stopped\n");
 }
 
+
+
+
 int tm_startup()
 {
-   /* building the hash table*/
-   hash_table = init_hash_table();
-   if (!hash_table)
-      return -1;
-
-#define init_timer(_id,_handler) \
-	hash_table->timers[(_id)].timeout_handler=(_handler); \
-	hash_table->timers[(_id)].id=(_id);
-
-   init_timer( RT_T1_TO_1, retransmission_handler );
-   init_timer( RT_T1_TO_2, retransmission_handler );
-   init_timer( RT_T1_TO_3, retransmission_handler );
-   init_timer( RT_T2, retransmission_handler );
-   init_timer( FR_TIMER_LIST, final_response_handler );
-   init_timer( FR_INV_TIMER_LIST, final_response_handler );
-   init_timer( WT_TIMER_LIST, wait_handler );
-   init_timer( DELETE_LIST, delete_handler );
-
-   /* register the timer function */
-   register_timer( timer_routine , hash_table , 1 );
-
-   /*first msg id*/
-   global_msg_id = 0;
-   T = T_UNDEFINED;
-
-   return 0;
+	/* building the hash table*/
+	hash_table = init_hash_table();
+	if (!hash_table)
+		return -1;
+
+	/* init. timer lists */
+	hash_table->timers[RT_T1_TO_1].id = RT_T1_TO_1;
+	hash_table->timers[RT_T1_TO_2].id = RT_T1_TO_2;
+	hash_table->timers[RT_T1_TO_3].id = RT_T1_TO_3;
+	hash_table->timers[RT_T2].id      = RT_T2;
+	hash_table->timers[FR_TIMER_LIST].id     = FR_TIMER_LIST;
+	hash_table->timers[FR_INV_TIMER_LIST].id = FR_INV_TIMER_LIST;
+	hash_table->timers[WT_TIMER_LIST].id     = WT_TIMER_LIST;
+	hash_table->timers[DELETE_LIST].id       = DELETE_LIST;
+
+	/* register the timer function */
+	register_timer( timer_routine , hash_table , 1 );
+
+	/*first msg id*/
+	global_msg_id = 0;
+	T = T_UNDEFINED;
+
+	return 0;
 }
 
 
@@ -150,7 +158,7 @@ void tm_shutdown()
 	while (tl!=end) {
 		tmp=tl->next_tl;
 		free_cell((struct cell*)tl->payload);
-		 tl=tmp;
+		tl=tmp;
 	}
 
 	/* destroy the hash table */
@@ -173,7 +181,6 @@ int t_add_transaction( struct sip_msg* p_msg )
 	struct cell*    new_cell;
 
 	DBG("DEBUG: t_add_transaction: adding......\n");
-
 	/* sanity check: ACKs can never establish a transaction */
 	if ( p_msg->REQ_METHOD==METHOD_ACK )
 	{
@@ -830,10 +837,13 @@ error:
 
 
 
-/*---------------------TIMEOUT HANDLERS--------------------------*/
+/*---------------------------TIMERS FUNCTIONS-------------------------------*/
+
+
+
 
 
-void retransmission_handler( void *attr)
+inline void retransmission_handler( void *attr)
 {
 	struct retrans_buff* r_buf ;
 	enum lists id;
@@ -847,9 +857,7 @@ void retransmission_handler( void *attr)
 	}	
 #endif
 
-
 	/*the transaction is already removed from RETRANSMISSION_LIST by timer*/
-
 	/* retransmision */
 	DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T);
 	if (r_buf->status!=STATUS_LOCAL_CANCEL && r_buf->status!=STATUS_REQUEST){
@@ -870,7 +878,7 @@ void retransmission_handler( void *attr)
 
 
 
-void final_response_handler( void *attr)
+inline void final_response_handler( void *attr)
 {
 	struct retrans_buff* r_buf = (struct retrans_buff*)attr;
 
@@ -917,7 +925,7 @@ void final_response_handler( void *attr)
 
 
 
-void wait_handler( void *attr)
+inline void wait_handler( void *attr)
 {
 	struct cell *p_cell = (struct cell*)attr;
 
@@ -945,7 +953,9 @@ void wait_handler( void *attr)
 }
 
 
-void delete_handler( void *attr)
+
+
+inline void delete_handler( void *attr)
 {
 	struct cell *p_cell = (struct cell*)attr;
 
@@ -961,6 +971,69 @@ void delete_handler( void *attr)
     DBG("DEBUG: delete_handler : done\n");
 }
 
+
+
+
+#define run_handler_for_each( _tl , _handler ) \
+	while ((_tl))\
+	{\
+		/* reset the timer list linkage */\
+		tmp_tl = (_tl)->next_tl;\
+		(_tl)->next_tl = (_tl)->prev_tl = 0;\
+		DBG("DEBUG: timer routine:%d,tl=%p next=%p\n",\
+			id,(_tl),tmp_tl);\
+		(_handler)( (_tl)->payload );\
+		(_tl) = tmp_tl;\
+	}
+
+
+
+
+void timer_routine(unsigned int ticks , void * attr)
+{
+	struct s_table    *hash_table = (struct s_table *)attr;
+	struct timer*      timers= hash_table->timers;
+	struct timer_link *tl, *tmp_tl;
+	int                id;
+
+#ifdef BOGDAN_TRIFLE
+	DBG(" %d \n",ticks);
+#endif
+
+	for( id=0 ; id<NR_OF_TIMER_LISTS ; id++ )
+	{
+		/* to waste as little time in lock as possible, detach list
+		   with expired items and process them after leaving the lock */
+		tl=check_and_split_time_list( &(hash_table->timers[ id ]), ticks);
+		/* process items now */
+		switch (id)
+		{
+			case FR_TIMER_LIST:
+			case FR_INV_TIMER_LIST:
+				run_handler_for_each(tl,final_response_handler);
+				break;
+			case RT_T1_TO_1:
+			case RT_T1_TO_2:
+			case RT_T1_TO_3:
+			case RT_T2:
+				run_handler_for_each(tl,retransmission_handler);
+				break;
+			case WT_TIMER_LIST:
+				run_handler_for_each(tl,wait_handler);
+				break;
+			case DELETE_LIST:
+				run_handler_for_each(tl,delete_handler);
+				break;
+		}
+	}
+}
+
+
+
+
+
+
+
 #ifndef _REALLY_TOO_OLD
 
 /* Builds an ACK request based on an INVITE request. ACK is send

+ 51 - 76
modules/tm/timer.c

@@ -8,42 +8,57 @@
 #include "timer.h"
 #include "../../dprint.h"
 
-int timer_group[NR_OF_TIMER_LISTS] = { 
+int timer_group[NR_OF_TIMER_LISTS] = 
+{
 	TG_FR, TG_FR,
 	TG_WT,
 	TG_DEL,
 	TG_RT, TG_RT, TG_RT, TG_RT
 };
 
+
+
+
 void reset_timer_list( struct s_table* hash_table, enum lists list_id)
 {
-	hash_table->timers[ list_id ].first_tl.next_tl = & (hash_table->timers[ list_id ].last_tl );
-	hash_table->timers[ list_id ].last_tl.prev_tl = & (hash_table->timers[ list_id ].first_tl );
-	hash_table->timers[ list_id ].first_tl.prev_tl = 
-		hash_table->timers[ list_id ].last_tl.next_tl = NULL;
-	hash_table->timers[ list_id ].last_tl.time_out = -1;
+	hash_table->timers[list_id].first_tl.next_tl =
+		&(hash_table->timers[list_id].last_tl );
+	hash_table->timers[list_id].last_tl.prev_tl =
+		&(hash_table->timers[list_id].first_tl );
+	hash_table->timers[list_id].first_tl.prev_tl =
+		hash_table->timers[list_id].last_tl.next_tl = NULL;
+	hash_table->timers[list_id].last_tl.time_out = -1;
 }
 
+
+
+
 void init_timer_list( struct s_table* hash_table, enum lists list_id)
 {
 	reset_timer_list( hash_table, list_id );
 	init_timerlist_lock( hash_table, list_id );
 }
 
+
+
+
 void print_timer_list(struct s_table* hash_table, enum lists list_id)
 {
-   struct timer* timer_list=&(hash_table->timers[ list_id ]);
-   struct timer_link *tl ;
-
-   tl = timer_list->first_tl.next_tl;
-   while (tl!=& timer_list->last_tl)
-   {
-      DBG("DEBUG: print_timer_list[%d]: %p, next=%p \n",list_id, tl, tl->next_tl);
-      tl = tl->next_tl;
-   }
+	struct timer* timer_list=&(hash_table->timers[ list_id ]);
+	struct timer_link *tl ;
+
+	tl = timer_list->first_tl.next_tl;
+	while (tl!=& timer_list->last_tl)
+	{
+		DBG("DEBUG: print_timer_list[%d]: %p, next=%p \n",
+			list_id, tl, tl->next_tl);
+		tl = tl->next_tl;
+	}
 }
 
-/* static void remove_from_timer_list_dummy(  struct timer_link* tl ) */
+
+
+
 void remove_timer_unsafe(  struct timer_link* tl )
 {
 #ifdef EXTRA_DEBUG
@@ -55,7 +70,6 @@ void remove_timer_unsafe(  struct timer_link* tl )
 	};
 #endif
 
-
 	if (is_in_timer_list2( tl )) {
 		tl->prev_tl->next_tl = tl->next_tl;
 		tl->next_tl->prev_tl = tl->prev_tl;
@@ -65,11 +79,13 @@ void remove_timer_unsafe(  struct timer_link* tl )
 	}
 }
 
+
+
+
 /* put a new cell into a list nr. list_id within a hash_table;
-  * set initial timeout
-  */
-void add_timer_unsafe( struct timer *timer_list,
-	struct timer_link *tl, unsigned int time_out )
+   set initial timeout */
+void add_timer_unsafe( struct timer *timer_list, struct timer_link *tl,
+													unsigned int time_out )
 {
 #ifdef EXTRA_DEBUG
 	if (timer_list->last_tl.prev_tl==0) {
@@ -79,31 +95,27 @@ void add_timer_unsafe( struct timer *timer_list,
 	};
 #endif
 
-	/*	remove_from_timer_list( tl ); */
-	/* the entire timer list is locked now -- noone else can manipulate it */
-	/* lock( timer_list->mutex ); */
 	tl->time_out = time_out;
 	tl->prev_tl = timer_list->last_tl.prev_tl;
 	tl->next_tl = & timer_list->last_tl;
 	timer_list->last_tl.prev_tl = tl;
 	tl->prev_tl->next_tl = tl;
 	tl->timer_list = timer_list;
-#	ifdef EXTRA_DEBUG
-		if ( tl->tg != timer_group[ timer_list->id ] ) {
-			LOG( L_CRIT, "CRITICAL error: changing timer group\n");
-			abort();
-		}
-#	endif
-	/* give the list lock away */
-	/* unlock( timer_list->mutex ); */
+#ifdef EXTRA_DEBUG
+	if ( tl->tg != timer_group[ timer_list->id ] ) {
+		LOG( L_CRIT, "CRITICAL error: changing timer group\n");
+		abort();
+	}
+#endif
 	DBG("DEBUG: add_to_tail_of_timer[%d]: %p\n",timer_list->id,tl);
 }
 
-/*
-	detach items passed by the time from timer list
-*/
-struct timer_link  *check_and_split_time_list( struct timer *timer_list, int time )
 
+
+
+/* detach items passed by the time from timer list */
+struct timer_link  *check_and_split_time_list( struct timer *timer_list,
+																int time )
 {
 	struct timer_link *tl , *tmp , *end, *ret;
 
@@ -141,47 +153,10 @@ struct timer_link  *check_and_split_time_list( struct timer *timer_list, int tim
 		abort();
 	};
 #endif
+	/* give the list lock away */
+	unlock(timer_list->mutex);
 
-
-   /* give the list lock away */
-   unlock(timer_list->mutex);
-
-   return ret;
-}
-
-
-
-
-
-void timer_routine(unsigned int ticks , void * attr)
-{
-	struct s_table       *hash_table = (struct s_table *)attr;
-	struct timer*          timers= hash_table->timers;
-	struct timer_link  *tl, *tmp_tl;
-	int                           id;
-
-#ifdef BOGDAN_TRIFLE
-	DBG(" %d \n",ticks);
-#endif
-
-	for( id=0 ; id<NR_OF_TIMER_LISTS ; id++ )
-	{
-		/* to waste as little time in lock as possible, detach list
-		   with expired items and process them after leaving the
-		   lock
-		*/
-		tl = check_and_split_time_list( & (hash_table->timers[ id ]), ticks );
-		/* process items now */
-		while (tl)
-		{
-			/* reset the timer list linkage */
-			tmp_tl = tl->next_tl;
-			tl->next_tl = tl->prev_tl =0 ; 
-			DBG("DEBUG: timer routine:timer[%d],tl=%p next=%p\n",id,tl,tmp_tl);
-			timers[id].timeout_handler( tl->payload );
-			tl = tmp_tl;
-		}
-	}
+	return ret;
 }
 
 

+ 32 - 43
modules/tm/timer.h

@@ -7,69 +7,58 @@
 
 #include "lock.h"
 
-/* identifiers of timer lists; 
-*/
-enum lists {
+
+
+
+/* identifiers of timer lists;*/
+/* fixed-timer retransmission lists (benefit: fixed timer$
+   length allows for appending new items to the list as$
+   opposed to inserting them which is costly */
+enum lists
+{
 	FR_TIMER_LIST, FR_INV_TIMER_LIST,
-	WT_TIMER_LIST, 
-	DELETE_LIST, 
-	/* fixed-timer retransmission lists (benefit: fixed timer
-	   length allows for appending new items to the list as
-		opposed to inserting them which is costly */
-	RT_T1_TO_1, RT_T1_TO_2, RT_T1_TO_3, RT_T2, 
-	NR_OF_TIMER_LISTS };
+	WT_TIMER_LIST,
+	DELETE_LIST,
+	RT_T1_TO_1, RT_T1_TO_2, RT_T1_TO_3, RT_T2,
+	NR_OF_TIMER_LISTS
+};
 
 
-extern int timer_group[NR_OF_TIMER_LISTS];
 
 #define is_in_timer_list2(_tl) ( (_tl)->timer_list )
+extern int timer_group[NR_OF_TIMER_LISTS];
+struct timer;
 
 
-struct timer;
 
-/* all you need to put a cell in a timer list:
-   links to neighbours and timer value         */
+/* all you need to put a cell in a timer list
+   links to neighbours and timer value */
 typedef struct timer_link
 {
-	struct timer_link 	*next_tl;
-	struct timer_link 	*prev_tl;
-	unsigned int       	time_out;
-	void				*payload;
-	struct timer		*timer_list;
-	/* ser_lock_t			*mutex; */
-	enum timer_groups	tg;
+	struct timer_link *next_tl;
+	struct timer_link *prev_tl;
+	unsigned int       time_out;
+	void              *payload;
+	struct timer      *timer_list;
+	enum timer_groups  tg;
 }timer_link_type ;
 
 
 /* timer list: includes head, tail and protection semaphore */
 typedef struct  timer
 {
-   struct timer_link first_tl;
-   struct timer_link last_tl;
-   ser_lock_t*         mutex;
-   enum lists id;
-   void                      (*timeout_handler)(void*);
+	struct timer_link  first_tl;
+	struct timer_link  last_tl;
+	ser_lock_t*        mutex;
+	enum lists         id;
 } timer_type;
 
-void init_timer_list( struct s_table* hash_table, enum lists list_id);
-void reset_timer_list( struct s_table* hash_table, enum lists list_id);
 
-/*
-void add_to_tail_of_timer_list( struct timer *timer_list, 
-	struct timer_link *tl, unsigned int time_out );
-void remove_from_timer_list( struct timer_link *tl);
-*/
-void timer_routine(unsigned int, void *);
 
+void init_timer_list( struct s_table* hash_table, enum lists list_id);
+void reset_timer_list( struct s_table* hash_table, enum lists list_id);
 void remove_timer_unsafe(  struct timer_link* tl ) ;
-void add_timer_unsafe( struct timer *timer_list,
-	struct timer_link *tl, unsigned int time_out );
-
-
-
-/* deprecated -- too expensive -- use appending instead 
-void insert_into_timer_list( struct s_table* hash_table , 
-	struct timer_link* tl, enum lists list_id , unsigned int time_out );
-*/
+void add_timer_unsafe( struct timer*, struct timer_link*, unsigned int);
+struct timer_link  *check_and_split_time_list( struct timer*, int);
 
 #endif

+ 76 - 47
parse_to.c

@@ -7,8 +7,10 @@
 #include "mem/mem.h"
 
 
-enum{ START_TO, QUOTED, ENCLOSED, BODY
-	, F_CR, F_LF, F_CRLF
+enum{ START_TO, DISPLAY_QUOTED, E_DISPLAY_QUOTED, DISPLAY_TOKEN
+	, S_URI_ENCLOSED, URI_ENCLOSED, E_URI_ENCLOSED
+	, URI_OR_TOKEN, MAYBE_URI_END
+	, END, F_CR, F_LF, F_CRLF
 	};
 
 enum{ S_PARA_NAME=20, PARA_NAME, S_EQUAL, S_PARA_VALUE, TAG1, TAG2, TAG3
@@ -192,7 +194,8 @@ char* parse_to_param(char *buffer, char *end, struct to_body *to_b,
 					case PARA_START:
 						*tmp=0;
 					case E_PARA_VALUE:
-						param = (struct to_param*)pkg_malloc(sizeof(struct to_param));
+						param = (struct to_param*)
+							pkg_malloc(sizeof(struct to_param));
 						if (!param){
 							LOG( L_ERR , "ERROR: parse_to_param"
 							" - out of memory\n" );
@@ -389,9 +392,8 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 	struct to_param *param=0;
 	int status = START_TO;
 	int saved_status;
-	char  *tmp,*posible_end;
+	char  *tmp,*foo;
 
-	posible_end = 0;
 	for( tmp=buffer; tmp<end; tmp++)
 	{
 		switch(*tmp)
@@ -406,12 +408,27 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 						/*previous=crlf and now =' '*/
 						status=saved_status;
 						break;
+					case URI_ENCLOSED:
+						to_b->body.len = tmp - to_b->body.s;
+						*tmp = 0;
+						status = E_URI_ENCLOSED;
+						break;
+					case URI_OR_TOKEN:
+						foo = tmp;
+						status = MAYBE_URI_END;
+						break;
 				}
 				break;
 			case '\n':
 				switch (status)
 				{
-					case BODY:
+					case URI_OR_TOKEN:
+						foo = tmp;
+						status = MAYBE_URI_END;
+					case MAYBE_URI_END:
+					case DISPLAY_TOKEN:
+					case E_DISPLAY_QUOTED:
+					case END:
 						saved_status=status;
 						status=F_LF;
 						break;
@@ -430,7 +447,13 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 			case '\r':
 				switch (status)
 				{
-					case BODY:
+					case URI_OR_TOKEN:
+						foo = tmp;
+						status = MAYBE_URI_END;
+					case MAYBE_URI_END:
+					case DISPLAY_TOKEN:
+					case E_DISPLAY_QUOTED:
+					case END:
 						saved_status=status;
 						status=F_CR;
 						break;
@@ -446,10 +469,9 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 				}
 				break;
 			case '\\':
-				posible_end = 0;
 				switch (status)
 				{
-					case QUOTED:
+					case DISPLAY_QUOTED:
 						switch (*(tmp+1))
 						{
 							case '\n':
@@ -465,15 +487,18 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 				}
 				break;
 			case '<':
-				posible_end = 0;
 				switch (status)
 				{
-					case QUOTED:
-						break;
 					case START_TO:
-						to_b->body.s = tmp;
-					case BODY:
-						status = ENCLOSED;
+						status = S_URI_ENCLOSED;
+						break;
+					case DISPLAY_QUOTED:
+						break;
+					case E_DISPLAY_QUOTED:
+					case URI_OR_TOKEN:
+					case DISPLAY_TOKEN: 
+					case MAYBE_URI_END:
+						status = S_URI_ENCLOSED;
 						break;
 					case F_CRLF:
 					case F_LF:
@@ -489,12 +514,14 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 			case '>':
 				switch (status)
 				{
-					case QUOTED:
-						posible_end = tmp;
+					case DISPLAY_QUOTED:
 						break;
-					case ENCLOSED:
-						posible_end = tmp;
-						status = BODY;
+					case URI_ENCLOSED:
+						*tmp = 0;
+					case E_URI_ENCLOSED:
+						to_b->body.len = tmp - to_b->body.s;
+						status = END;
+						foo = 0;
 						break;
 					case F_CRLF:
 					case F_LF:
@@ -508,16 +535,13 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 				}
 				break;
 			case '"':
-				posible_end = 0;
 				switch (status)
 				{
 					case START_TO:
-						to_b->body.s = tmp;
-					case BODY:
-						status = QUOTED;
+						status = DISPLAY_QUOTED;
 						break;
-					case QUOTED:
-						status = BODY;
+					case DISPLAY_QUOTED:
+						status = E_DISPLAY_QUOTED;
 						break;
 					case F_CRLF:
 					case F_LF:
@@ -533,17 +557,20 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 			case ';' :
 				switch (status)
 				{
-					case QUOTED:
-					case ENCLOSED:
-						posible_end = 0;
-						break;
-					case BODY:
+					case DISPLAY_QUOTED:
+					case URI_ENCLOSED:
+						break;
+					case URI_OR_TOKEN:
+						foo = tmp;
+					case MAYBE_URI_END:
+						to_b->body.len = foo - to_b->body.s;
+					case END:
 						tmp = parse_to_param(tmp,end,to_b,&saved_status);
+						if (foo) *foo=0;
 						goto endofheader;
 					case F_CRLF:
 					case F_LF:
 					case F_CR:
-						posible_end = 0;
 						/*previous=crlf and now !=' '*/
 						goto endofheader;
 					default:
@@ -557,13 +584,18 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 				{
 					case START_TO:
 						to_b->body.s=tmp;
-						posible_end = tmp;
-						status = BODY;
+						status = URI_OR_TOKEN;;
+						break;
+					case S_URI_ENCLOSED:
+						to_b->body.s=tmp;
+						status=URI_ENCLOSED;
 						break;
-					case QUOTED:
-					case ENCLOSED:
-					case BODY:
-						posible_end = tmp;
+					case MAYBE_URI_END:
+						status = DISPLAY_TOKEN;
+					case DISPLAY_QUOTED:
+					case DISPLAY_TOKEN:
+					case URI_ENCLOSED:
+					case URI_OR_TOKEN:
 						break;
 					case F_CRLF:
 					case F_LF:
@@ -579,20 +611,17 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
 	}/*for*/
 
 endofheader:
+	DBG("DEBUG: status = %d \n",status);
 	status=saved_status;
 	DBG("end of header reached, state=%d\n", status);
 	/* check if error*/
 	switch(status){
-		case BODY:
+		case MAYBE_URI_END:
+			*foo=0;
+			to_b->body.len = foo - to_b->body.s;
+		case END:
 		case E_PARA_VALUE:
-			if (posible_end){
-				*(posible_end+1) = 0;
-				to_b->body.len=(posible_end+1)-to_b->body.s;
-			}else{
-				LOG(L_ERR, "ERROR: parse_to: invalid To - unexpected "
-					"end of header in %d status\n", status);
-				goto error;
-			}
+			*(tmp-1)=0;
 			break;
 		default:
 			LOG(L_ERR, "ERROR: parse_to: invalid To -  unexpected "