error.c
1400b772
 /*
  * $Id$
  *
7dd0b342
  *
53c7e0f1
  * Copyright (C) 2001-2003 FhG Fokus
7dd0b342
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
b2fcef3c
  *
  * History:
  * --------
  * 2003-04-04 phrase length corrected not to include trailer 0 (jiri)
1400b772
  */
 
7dd0b342
 
b0e03da6
 #include <stdio.h>
1400b772
 #include "error.h"
caf80ae6
 #include "str.h"
 #include "parser/msg_parser.h"
 #include "mem/mem.h"
1400b772
 
 /* current function's error; */
 int ser_error=-1;
 /* previous error */
 int prev_ser_error=-1;
 
 int err2reason_phrase( 
53c7e0f1
 	int ser_error,  /* current internal ser error */
1400b772
 	int *sip_error,  /* the sip error code to which ser 	
 					    ser error will be turned */
 	char *phrase,    /* resulting error text */
 	int etl, 		/* error text buffer length */
 	char *signature ) /* extra text to be appended */
 {
 
 	char *error_txt;
 
 	switch( ser_error ) {
 		case E_SEND:
53c7e0f1
 			error_txt="Unfortunately error on sending to next hop occurred";
1400b772
 			*sip_error=-ser_error;
 			break;
 		case E_BAD_ADDRESS:
53c7e0f1
 			error_txt="Unresolvable destination";
1400b772
 			*sip_error=-ser_error;
 			break;
 		case E_BAD_REQ:
 			error_txt="Bad Request";
 			*sip_error=-ser_error;
 			break;
 		case E_BAD_URI:
53c7e0f1
 			error_txt="Regretfully, we were not able to process the URI";
1400b772
 			*sip_error=-ser_error;
 			break;
caf80ae6
 		case E_BAD_TUPEL:
53c7e0f1
 			error_txt="Transaction tuple incomplete";
caf80ae6
 			*sip_error=-E_BAD_REQ;
 			break;
d5191539
 		case E_BAD_TO:
 			error_txt="Bad To";
 			*sip_error=-E_BAD_REQ;
 			break;
30449150
 		case E_EXEC:
 			error_txt="Error in external logic";
 			*sip_error=-E_BAD_SERVER;
 			break;
 		case E_TOO_MANY_BRANCHES:
 			error_txt="Forking capacity exceeded";
 			*sip_error=-E_BAD_SERVER;
 			break;
0b4b7601
 
 	        case E_Q_INV_CHAR:
 			error_txt="Invalid character in q parameter";
 			*sip_error=-E_BAD_REQ;
 			break;
 
 	        case E_Q_EMPTY:
 			error_txt="Empty q parameter";
 			*sip_error=-E_BAD_REQ;
 			break;;
 
 	        case E_Q_TOO_BIG:
 			error_txt="q parameter too big";
 			*sip_error=-E_BAD_REQ;
 			break;
 
 	        case E_Q_DEC_MISSING:
 			error_txt="Decimal part missing in q";
 			*sip_error=-E_BAD_REQ;
 			break;
 
5c55191d
 		case E_CANCELED:
 			error_txt="transaction canceled";
 			*sip_error=-ser_error;
 			break;
 
a82841fa
 		case E_OUT_OF_MEM:
 		/* dont disclose lack of mem in release mode */
af93cbdf
 #ifdef EXTRA_DEBUG
a82841fa
 			error_txt="Excuse me I ran out of memory";
 			*sip_error=500;
 			break;
 #endif
2f0f1a30
 		case E_OK:
 			error_txt="No error";
 			*sip_error=500;
 			break;
1400b772
 		default:
53c7e0f1
 			error_txt="I'm terribly sorry, server error occurred";
1400b772
 			*sip_error=500;
 			break;
 	}
 	return snprintf( phrase, etl, "%s (%d/%s)", error_txt, 
 		-ser_error, signature );
 }
caf80ae6
 
 char *error_text( int code )
 {
 	switch(code) {
 
 		case 100: return "Trying";
 		case 180: return "Ringing";
 		case 181: return "Call is Being Forwarded";
 		case 182: return "Queued";
 		case 183: return "Session Progress";
 
 		case 200: return "OK";
 
 		case 300: return "Multiple Choices";
 		case 301: return "Moved Permanently";
 		case 302: return "Moved Temporarily";
 		case 305: return "Use Proxy";
 		case 380: return "Alternative Service";
 
 		case 400: return "Bad Request";
 		case 401: return "Unauthorized";
53c7e0f1
 		case 402: return "Payment Required";
caf80ae6
 		case 403: return "Forbidden";
 		case 404: return "Not Found";
 		case 405: return "Method not Allowed";
 		case 406: return "Not Acceptable";
 		case 407: return "Proxy authentication Required";
 		case 408: return "Request Timeout";
 		case 410: return "Gone";
 		case 413: return "Request Entity Too Large";
 		case 414: return "Request-URI Too Long";
 		case 415: return "Unsupported Media Type";
 		case 416: return "Unsupported URI Scheme";
 		case 417: return "Bad Extension";
 		case 421: return "Extension Required";
 		case 423: return "Interval Too Brief";
 		case 480: return "Temporarily Unavailable";
 		case 481: return "Call/Transaction Does not Exist";
 		case 482: return "Loop Detected";
 		case 483: return "Too Many Hops";
 		case 484: return "Address Incomplete";
53c7e0f1
 		case 485: return "Ambiguous";
caf80ae6
 		case 486: return "Busy Here";
 		case 487: return "Request Terminated";
 		case 488: return "Not Acceptable Here";
 		case 491: return "Request Pending";
 	
 		case 500: return "Server Internal Error";
 		case 501: return "Not Implemented";
 		case 502: return "Bad Gateway";
 		case 503: return "Service Unavailable";
 		case 504: return "Server Time-out";
 		case 505: return "Version not Supported";
 		case 513: return "Message Too Large";
 
 		case 600: return "Busy Everywhere";
 		case 603: return "Decline";
 		case 604: return "Does not Exist Anywhere";
 		case 606: return "Not Acceptable";
 
 	}
 
 	if (code>=600) return "Global Failure";
 	else if (code>=500) return "Server Failure";
 	else if (code>=400) return "Request Failure";
 	else if (code>=300) return "Redirection";
 	else if (code>=200) return "Successful";
 	else if (code>=100) return "Provisional";
 	else return "Unspecified";
 }
 
 void get_reply_status( str *status, struct sip_msg *reply, int code )
 {
 	str phrase;
 
 	status->s=0;
 
 	if (reply==0) {
 		LOG(L_CRIT, "BUG: get_reply_status called with 0 msg\n");
 		return;
 	}
 
 	if (reply==FAKED_REPLY) {
 		phrase.s=error_text(code);
 		phrase.len=strlen(phrase.s);
 	} else {
 		phrase=reply->first_line.u.reply.reason;
 	}
b2fcef3c
 	status->len=phrase.len+3/*code*/+1/*space*/; 
 	status->s=pkg_malloc(status->len+1/*ZT */);
caf80ae6
 	if (!status->s) {
 		LOG(L_ERR, "ERROR: get_reply_status: no mem\n");
 		return;
 	}
 	status->s[3]=' ';
 	status->s[2]='0'+code % 10; code=code/10;
 	status->s[1]='0'+code% 10; code=code/10;
 	status->s[0]='0'+code % 10;
 	memcpy(&status->s[4], phrase.s, phrase.len);
b2fcef3c
 	status->s[status->len]=0;
caf80ae6
 }