![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
netsock.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Kevin P. Fleming <kpfleming@digium.com> 00007 * Mark Spencer <markster@digium.com> 00008 * 00009 * See http://www.asterisk.org for more information about 00010 * the Asterisk project. Please do not directly contact 00011 * any of the maintainers of this project for assistance; 00012 * the project provides a web site, mailing lists and IRC 00013 * channels for your use. 00014 * 00015 * This program is free software, distributed under the terms of 00016 * the GNU General Public License Version 2. See the LICENSE file 00017 * at the top of the source tree. 00018 */ 00019 00020 /*! \file 00021 * 00022 * \brief Network socket handling 00023 * 00024 * \author Kevin P. Fleming <kpfleming@digium.com> 00025 * \author Mark Spencer <markster@digium.com> 00026 */ 00027 00028 #include "asterisk.h" 00029 00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 44968 $") 00031 00032 #include <stdio.h> 00033 #include <stdlib.h> 00034 #include <string.h> 00035 #include <sys/time.h> 00036 #include <signal.h> 00037 #include <errno.h> 00038 #include <unistd.h> 00039 #include <netinet/in.h> 00040 #include <arpa/inet.h> 00041 #include <sys/socket.h> 00042 #include <netdb.h> 00043 #include <net/if.h> 00044 #include <netinet/in_systm.h> 00045 #include <netinet/ip.h> 00046 #include <sys/ioctl.h> 00047 00048 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) 00049 #include <fcntl.h> 00050 #include <net/route.h> 00051 #endif 00052 00053 #if defined (SOLARIS) 00054 #include <sys/sockio.h> 00055 #endif 00056 00057 #include "asterisk/netsock.h" 00058 #include "asterisk/logger.h" 00059 #include "asterisk/channel.h" 00060 #include "asterisk/options.h" 00061 #include "asterisk/utils.h" 00062 #include "asterisk/lock.h" 00063 #include "asterisk/srv.h" 00064 00065 struct ast_netsock { 00066 ASTOBJ_COMPONENTS(struct ast_netsock); 00067 struct sockaddr_in bindaddr; 00068 int sockfd; 00069 int *ioref; 00070 struct io_context *ioc; 00071 void *data; 00072 }; 00073 00074 struct ast_netsock_list { 00075 ASTOBJ_CONTAINER_COMPONENTS(struct ast_netsock); 00076 struct io_context *ioc; 00077 }; 00078 00079 static void ast_netsock_destroy(struct ast_netsock *netsock) 00080 { 00081 ast_io_remove(netsock->ioc, netsock->ioref); 00082 close(netsock->sockfd); 00083 free(netsock); 00084 } 00085 00086 struct ast_netsock_list *ast_netsock_list_alloc(void) 00087 { 00088 return ast_calloc(1, sizeof(struct ast_netsock_list)); 00089 } 00090 00091 int ast_netsock_init(struct ast_netsock_list *list) 00092 { 00093 memset(list, 0, sizeof(*list)); 00094 ASTOBJ_CONTAINER_INIT(list); 00095 00096 return 0; 00097 } 00098 00099 int ast_netsock_release(struct ast_netsock_list *list) 00100 { 00101 ASTOBJ_CONTAINER_DESTROYALL(list, ast_netsock_destroy); 00102 ASTOBJ_CONTAINER_DESTROY(list); 00103 00104 return 0; 00105 } 00106 00107 struct ast_netsock *ast_netsock_find(struct ast_netsock_list *list, 00108 struct sockaddr_in *sa) 00109 { 00110 struct ast_netsock *sock = NULL; 00111 00112 ASTOBJ_CONTAINER_TRAVERSE(list, !sock, { 00113 ASTOBJ_RDLOCK(iterator); 00114 if (!inaddrcmp(&iterator->bindaddr, sa)) 00115 sock = iterator; 00116 ASTOBJ_UNLOCK(iterator); 00117 }); 00118 00119 return sock; 00120 } 00121 00122 struct ast_netsock *ast_netsock_bindaddr(struct ast_netsock_list *list, struct io_context *ioc, struct sockaddr_in *bindaddr, int tos, ast_io_cb callback, void *data) 00123 { 00124 int netsocket = -1; 00125 int *ioref; 00126 00127 struct ast_netsock *ns; 00128 00129 /* Make a UDP socket */ 00130 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 00131 00132 if (netsocket < 0) { 00133 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 00134 return NULL; 00135 } 00136 if (bind(netsocket,(struct sockaddr *)bindaddr, sizeof(struct sockaddr_in))) { 00137 ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(bindaddr->sin_addr), ntohs(bindaddr->sin_port), strerror(errno)); 00138 close(netsocket); 00139 return NULL; 00140 } 00141 if (option_verbose > 1) 00142 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos); 00143 00144 if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 00145 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 00146 00147 ast_enable_packet_fragmentation(netsocket); 00148 00149 if (!(ns = ast_calloc(1, sizeof(struct ast_netsock)))) { 00150 close(netsocket); 00151 return NULL; 00152 } 00153 00154 /* Establish I/O callback for socket read */ 00155 if (!(ioref = ast_io_add(ioc, netsocket, callback, AST_IO_IN, ns))) { 00156 close(netsocket); 00157 free(ns); 00158 return NULL; 00159 } 00160 ASTOBJ_INIT(ns); 00161 ns->ioref = ioref; 00162 ns->ioc = ioc; 00163 ns->sockfd = netsocket; 00164 ns->data = data; 00165 memcpy(&ns->bindaddr, bindaddr, sizeof(ns->bindaddr)); 00166 ASTOBJ_CONTAINER_LINK(list, ns); 00167 00168 return ns; 00169 } 00170 00171 struct ast_netsock *ast_netsock_bind(struct ast_netsock_list *list, struct io_context *ioc, const char *bindinfo, int defaultport, int tos, ast_io_cb callback, void *data) 00172 { 00173 struct sockaddr_in sin; 00174 char *tmp; 00175 char *host; 00176 char *port; 00177 int portno; 00178 00179 memset(&sin, 0, sizeof(sin)); 00180 sin.sin_family = AF_INET; 00181 sin.sin_port = htons(defaultport); 00182 tmp = ast_strdupa(bindinfo); 00183 00184 host = strsep(&tmp, ":"); 00185 port = tmp; 00186 00187 if (port && ((portno = atoi(port)) > 0)) 00188 sin.sin_port = htons(portno); 00189 00190 inet_aton(host, &sin.sin_addr); 00191 00192 return ast_netsock_bindaddr(list, ioc, &sin, tos, callback, data); 00193 } 00194 00195 int ast_netsock_sockfd(const struct ast_netsock *ns) 00196 { 00197 return ns ? ns-> sockfd : -1; 00198 } 00199 00200 const struct sockaddr_in *ast_netsock_boundaddr(const struct ast_netsock *ns) 00201 { 00202 return &(ns->bindaddr); 00203 } 00204 00205 void *ast_netsock_data(const struct ast_netsock *ns) 00206 { 00207 return ns->data; 00208 } 00209 00210 void ast_netsock_unref(struct ast_netsock *ns) 00211 { 00212 ASTOBJ_UNREF(ns, ast_netsock_destroy); 00213 }