// $Id: common.c,v 1.2 2005/03/14 10:23:27 lynx Exp $ // vim:syntax=lpc #include #include "sip.h" mapping SIP_PHRASES; mapping specialCases; load() { specialCases = ([ "Cseq" : "CSeq", "Call-Id" : "Call-ID", "Www-Authenticate" : "WWW-Authenticate", ]); SIP_PHRASES = ([ // 100: "Trying", 180: "Ringing", 181: "Call Is Being Forwarded", 182: "Queued", 183: "Session Progress", // 200: "OK", // 300: "Multiple Choices", 301: "Moved Permanently", 302: "Moved Temporarily", 303: "See Other", 305: "Use Proxy", 380: "Alternative Service", // 400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Timeout", 409: "Conflict", 410: "Gone", 411: "Length Required", 413: "Request Entity Too Large", 414: "Request-URI Too Large", 415: "Unsupported Media Type", 416: "Unsupported URI Scheme", 420: "Bad Extension", 421: "Extension Required", 423: "Interval Too Brief", 480: "Temporarily Unavailable", 481: "Call/Transaction Does Not Exist", 482: "Loop Detected", 483: "Too Many Hops", 484: "Address Incomplete", 485: "Ambiguous", 486: "Busy Here", 487: "Request Terminated", 488: "Not Acceptable Here", 491: "Request Pending", 493: "Undecipherable", // 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Server Time-out", 505: "SIP Version not supported", 513: "Message Too Large", // 600: "Busy Everywhere", 603: "Decline", 604: "Does not exist anywhere", 606: "Not Acceptable" ]); } encodevar(varname) { int i; i = index(varname, '-'); if(i != -1) varname = upper_case(varname[0..0]) + varname[1..i] + upper_case(varname[i+1..i+1]) + varname[i+2..]; else varname = capitalize(varname); return specialCases[varname] || varname; } serialize(varnames, vars, data) { string varname; mixed value; string t; t = ""; foreach(varname : varnames) { value = vars[varname]; varname = encodevar(varname); if (pointerp(value)) { string v; foreach (v : value) t += varname + ": " + v + CRLF; } else if (stringp(value)) t += varname + ": " + value + CRLF; } if (data && stringp(data)) { if (strlen(data)) t += "Content-Type: " + vars["content-type"] + CRLF; t += "Content-Length: " + strlen(data) + CRLF CRLF; // TODO: how to end packet? t += data; } return t; } string makeResponse(string prot, int code, mapping v, mixed data) { string reply; reply = prot + " " + code + " " + SIP_PHRASES[code] + CRLF + serialize(({ "from", "to", "via", "call-id", "cseq", "www-authenticate" }), v); if (data && stringp(data)) { if (v["content-type"]) reply += "Content-Type: " + v["content-type"] + CRLF; reply += "Content-Length: " + strlen(data); reply += data + CRLF CRLF; } return reply; } parseHeaders(string headers) { string line; mapping v; v = ([ ]); foreach(line : explode(headers, CRLF)) { string key, val; unless(sscanf(line, "%s:%t%s", key, val) == 2) { P3(("SIP parse: strange line %O\n", line)) // TODO 400 bad request? continue; } key = lower_case(key); val = chomp(val); if (pointerp(v[ key ]) ) v[ key ] += ({ val }); else if (v[ key ]) v[ key ] = ({ v[ key ], val }); else v[ key ] = chomp(val); } return v; }