📄 sip_itf.c
字号:
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END *//* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */#pragma ident "@(#)sip_itf.c 1.19 06/08/16 SMI"#ifdef __linux__#include <stdarg.h>#else#include <sys/varargs.h>#endif#include "sip_miscdefs.h"#include "sip_xaction.h"#include "sip_hash.h"#include "sip_dialog.h"#include "sip_msg.h"#define SIP_MSG_BUF_SZ 100void (*sip_ulp_recv)(const sip_conn_object_t, sip_msg_t, const sip_dialog_t) = NULL;uint_t (*sip_stack_timeout)(void *, void (*func)(void *), struct timeval *) = NULL;boolean_t (*sip_stack_untimeout)(uint_t) = NULL;void (*sip_ulp_dlg_del)(sip_dialog_t, sip_msg_t, void *) = NULL;int (*sip_stack_send)(sip_conn_object_t xonn_object, char *, int) = NULL;void (*sip_refhold_conn)(sip_conn_object_t) = NULL;void (*sip_refrele_conn)(sip_conn_object_t) = NULL;boolean_t (*sip_is_conn_stream)(sip_conn_object_t) = NULL;boolean_t (*sip_is_conn_reliable)(sip_conn_object_t) = NULL;int (*sip_conn_rem_addr)(sip_conn_object_t, struct sockaddr *, socklen_t *) = NULL;int (*sip_conn_local_addr)(sip_conn_object_t, struct sockaddr *, socklen_t *) = NULL;int (*sip_conn_transport)(sip_conn_object_t) = NULL;int (*sip_conn_timer1)(sip_conn_object_t) = NULL;int (*sip_conn_timer2)(sip_conn_object_t) = NULL;int (*sip_conn_timer4)(sip_conn_object_t) = NULL;int (*sip_conn_timerd)(sip_conn_object_t) = NULL;boolean_t sip_manage_dialog = B_FALSE;uint64_t sip_hash_salt = 0;/* Defaults, overridden by configured values, if any */int sip_timer_T1 = SIP_TIMER_T1;int sip_timer_T2 = SIP_TIMER_T2;int sip_timer_T4 = SIP_TIMER_T4;int sip_timer_TD = 32 * SIP_SECONDS;/* Create and send an error response */voidsip_send_resp_err(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg, int resp){ _sip_msg_t *sip_msg_resp; sip_msg_resp = (_sip_msg_t *)sip_create_response((sip_msg_t)sip_msg, resp, sip_get_resp_desc(resp), NULL, NULL); if (sip_msg_resp == NULL) { /* * Message was too bad to even create a * response. Just drop the messge. */ return; } /* * We directly send it to the transport here. */ if (sip_adjust_msgbuf(sip_msg_resp) != 0) { sip_free_msg((sip_msg_t)sip_msg_resp); return; } (void) sip_stack_send(conn_obj, sip_msg_resp->sip_msg_buf, sip_msg_resp->sip_msg_len);}/* Validate some of the common headers */boolean_tsip_check_common_headers(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg){ int err; if (sip_get_to_uri_str((sip_msg_t)sip_msg, &err) == NULL) goto error; if (sip_get_from_uri_str((sip_msg_t)sip_msg, &err) == NULL) goto error; if (sip_get_callseq_num((sip_msg_t)sip_msg, &err) < 0) goto error; if (sip_get_callid((sip_msg_t)sip_msg, &err) == NULL) goto error; return (B_FALSE);error: sip_send_resp_err(conn_obj, sip_msg, SIP_BAD_REQUEST); return (B_TRUE);}/* * setup pointers to where the headers are. */static intsip_setup_header_pointers(_sip_msg_t *sip_msg){ char *msg; _sip_header_t *sip_msg_header; char *end; msg = sip_msg->sip_msg_buf; end = sip_msg->sip_msg_buf + sip_msg->sip_msg_len; /* * Skip while space. */ while (isspace(*msg)) { if (msg < end) msg++; else return (EINVAL); } /* * We consider Request and Response line as a header */ for (;;) { /* * Skip CRLF */ if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) { if (sip_msg->sip_msg_headers_end != NULL) { SKIP_CRLF(msg); sip_msg->sip_msg_headers_end->sip_hdr_end = msg; } /* * Start of a header. * Check for empty line. */ if (strncmp(SIP_CRLF, msg, strlen(SIP_CRLF)) == 0) { /* * empty line, start of content. */ SKIP_CRLF(msg); sip_msg->sip_msg_headers_end->sip_hdr_end = msg; break; } /* * store start of header. */ sip_msg_header = calloc(1, sizeof (_sip_header_t)); if (sip_msg_header == NULL) return (EINVAL); sip_msg_header->sip_hdr_start = msg; sip_msg_header->sip_hdr_current = msg; sip_msg_header->sip_hdr_allocated = B_FALSE; sip_msg_header->sip_hdr_prev = sip_msg->sip_msg_headers_end; sip_msg_header->sip_hdr_next = NULL; sip_msg_header->sip_hdr_sipmsg = sip_msg; sip_msg->sip_msg_headers_end->sip_hdr_next = sip_msg_header; sip_msg->sip_msg_headers_end = sip_msg_header; } else { if (sip_msg->sip_msg_headers_start == NULL) { /* * Allocate first header structure. */ sip_msg_header = calloc(1, sizeof (_sip_header_t)); if (sip_msg_header == NULL) return (EINVAL); sip_msg_header->sip_hdr_allocated = B_FALSE; sip_msg_header->sip_hdr_start = msg; sip_msg_header->sip_hdr_current = msg; sip_msg_header->sip_hdr_sipmsg = sip_msg; sip_msg->sip_msg_headers_start = sip_msg_header; sip_msg->sip_msg_headers_end = sip_msg_header; } msg++; } /* * We have reached the end without hitting the empty line. */ if (msg - sip_msg->sip_msg_buf >= sip_msg->sip_msg_len) return (EINVAL); } if (sip_msg->sip_msg_headers_start == NULL) return (EPROTO); /* * Move start line to be a separate line. */ sip_msg->sip_msg_start_line = sip_msg->sip_msg_headers_start; sip_msg->sip_msg_headers_start = sip_msg->sip_msg_headers_start->sip_hdr_next; sip_msg->sip_msg_start_line->sip_hdr_prev = NULL; sip_msg->sip_msg_start_line->sip_hdr_next = NULL; if (sip_msg->sip_msg_headers_start == NULL) return (EINVAL); sip_msg->sip_msg_headers_start->sip_hdr_prev = NULL; /* * Deal with content. */ sip_msg->sip_msg_content = calloc(1, sizeof (sip_content_t)); sip_msg->sip_msg_content->sip_content_start = msg; sip_msg->sip_msg_content->sip_content_end = sip_msg->sip_msg_buf + sip_msg->sip_msg_len; sip_msg->sip_msg_content->sip_content_allocated = B_FALSE; sip_msg->sip_msg_content_len = sip_msg->sip_msg_content->sip_content_end - sip_msg->sip_msg_content->sip_content_start; return (0);}/* * The send interface to the sip stack. Used by upper layers. */intsip_sendmsg(sip_conn_object_t obj, sip_msg_t sip_msg, sip_dialog_t dialog, uint32_t flags){ sip_xaction_t *sip_trans = NULL; int ret = 0; sip_message_type_t *sip_msg_info; _sip_msg_t *_sip_msg; boolean_t stateful = flags & SIP_SEND_STATEFUL; boolean_t dlg_on_fork = flags & SIP_DIALOG_ON_FORK; sip_refhold_conn(obj); _sip_msg = (_sip_msg_t *)sip_msg; if ((ret = sip_adjust_msgbuf(_sip_msg)) != 0) { sip_refrele_conn(obj); return (ret); } assert(_sip_msg->sip_msg_req_res != NULL); sip_msg_info = _sip_msg->sip_msg_req_res; /* * Send it statefully if: * if stateful is set in 'flags' AND * this is not an ACK request, if it is a request (should the upper * layer set stateful in the latter case?, i.e is the check * necessary here?) */ if (stateful && (!sip_msg_info->is_request || sip_msg_info->sip_req_method != ACK)) { sip_trans = (sip_xaction_t *)sip_xaction_get(obj, sip_msg, B_TRUE, sip_msg_info->is_request ? SIP_CLIENT_TRANSACTION : SIP_SERVER_TRANSACTION, &ret); if (sip_trans == NULL) { sip_refrele_conn(obj); return (ret); } ret = sip_xaction_output(obj, sip_trans, _sip_msg); SIP_XACTION_REFCNT_DECR(sip_trans); if (ret != 0) { sip_refrele_conn(obj); return (ret); } } /* * If the appln wants us to create the dialog, create a partial * dialog at this stage, when we get the response, we will * complete it. */ if (sip_manage_dialog) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -