1/* 2 * Copyright (C) 2001-2005 Chris Ross, Stephan Engstrom, Alex Holden et al 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * o Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * o Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * o Neither the name of the ferite software nor the names of its contributors may 14 * be used to endorse or promote products derived from this software without 15 * specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30uses "stream"; 31uses "network"; 32 33module-header { 34#include "../network/util_network.h" 35} 36 37/** 38 * @namespace Network 39 * @modifies Network 40 */ 41namespace modifies Network 42{ 43 44 /** @namespace Unix @brief The Unix namespace provides a set of tools to access unix domain socket streams */ 45 namespace Unix { 46 47 /** 48 * @class Stream 49 * @extends Stream.StdioStream 50 * @brief Provides a Unix domain socket implementation of the Stream object 51 */ 52 class Stream extends Stream.StdioStream 53 { 54 /** 55 * @variable path @type string @brief The path the unix domain socket is connected on */ 56 string path; 57 58 /** 59 * @function accept 60 * @declaration function accept() 61 * @brief Accept an incoming connection 62 * @description This function will accept a connection and return a 63 * UnixStream object which can be used. This function will 64 * only work if the socket was initially created using 65 * Network.unix_bind(). 66 */ 67 native function accept() 68 { 69 FeriteVariable *obj, **args, *fv; 70 FeriteClass *cls; 71 int sock; 72 73 do 74 { 75 sock = accept((int)SelfObj->filedata, NULL, NULL); 76 } 77 while(sock == -1 && errno == EINTR); 78 79 if(sock == -1) 80 { 81 ferite_set_error(script, errno, "%s", strerror(errno)); 82 FE_RETURN_NULL_OBJECT; 83 } 84 85 if((cls = ferite_find_class(script, script->mainns, "Network.Unix.Stream"))) 86 { 87 args = ferite_create_parameter_list(4); 88 args = ferite_add_to_parameter_list(args, fe_new_lng_static("socket", sock)); 89 MARK_VARIABLE_AS_DISPOSABLE(args[0]); 90 obj = ferite_new_object(script, cls, args); 91 ferite_delete_parameter_list(script, args); 92 fv = ferite_object_get_var(script, self, "path"); 93 fv = ferite_create_string_variable(script, "path", VAS(fv), 94 FE_STATIC); 95 ferite_object_set_var(script, VAO(obj), "path", fv); 96 FE_RETURN_VAR(obj); 97 } 98 FE_RETURN_NULL_OBJECT; 99 } 100 101 /** 102 * @function listen 103 * @declaration function listen(number backlog) 104 * @brief Set the number of slots the system listens on for connections. 105 * @param number backlog The number of slots 106 */ 107 native function listen(number backlog) 108 { 109 int sock = (int)SelfObj->filedata; 110 int retval = listen(sock, (long)backlog); 111 FE_RETURN_LONG(retval); 112 } 113 } 114 /** 115 * @end 116 */ 117 118 /** 119 * @function connect 120 * @declaration function connect(string path) 121 * @brief Connect to a Unix domain socket at the specified location 122 * @param string path The full path to the named socket 123 * @return An object connected to the named socket, or null if the 124 * connection could not be established 125 */ 126 native function connect(string path) 127 { 128 FeriteVariable *obj, **args, *fv; 129 FeriteClass *cls; 130 struct sockaddr *sa; 131 struct sockaddr_un un; 132 int sock; 133 134 if((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) 135 FE_RETURN_NULL_OBJECT; 136 137 un.sun_family = AF_UNIX; 138 if(path->length + 1 > sizeof(un.sun_path)) 139 { 140 ferite_set_error(script, 0, "Path too long"); 141 FE_RETURN_NULL_OBJECT; 142 } 143 memcpy(un.sun_path, path->data, path->length + 1); 144 sa = (struct sockaddr*)&un; 145 146 if(connect(sock, sa, sizeof(struct sockaddr_un)) == -1) 147 { 148 ferite_set_error(script, errno, "%s", strerror(errno)); 149 close(sock); 150 FE_RETURN_NULL_OBJECT; 151 } 152 153 if((cls = ferite_find_class(script, script->mainns, "Network.Unix.Stream"))) 154 { 155 args = ferite_create_parameter_list(4); 156 args = ferite_add_to_parameter_list(args, fe_new_lng_static("socket", sock)); 157 MARK_VARIABLE_AS_DISPOSABLE(args[0]); /* automatically clear up */ 158 obj = ferite_new_object(script, cls, args); 159 ferite_delete_parameter_list(script, args); 160 fv = ferite_create_string_variable(script, "path", path, FE_STATIC); 161 ferite_object_set_var(script, VAO(obj), "path", fv); 162 FE_RETURN_VAR(obj); 163 } 164 FE_RETURN_NULL_OBJECT; 165 } 166 167 /** 168 * @function bind 169 * @declaration function bind(string path) 170 * @brief Bind to a Unix domain socket 171 * @param string path The full path to the file to use as the named socket 172 * @return An object that can accept connections, or null on error 173 * @description Creates a UnixStream object bound to the specified 174 * Unix domain socket. Note that the bind will fail if the 175 * file already exists, and Unix domain sockets are not 176 * automatically deleted when the server closes them, so 177 * you may need to delete a stale socket file before you can 178 * bind to it. 179 */ 180 native function bind(string path) 181 { 182 FeriteVariable *obj, **args, *fv; 183 FeriteClass *cls; 184 struct sockaddr *sa; 185 struct sockaddr_un un; 186 int sock; 187 188 if((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) 189 FE_RETURN_NULL_OBJECT; 190 191 un.sun_family = AF_UNIX; 192 if(path->length + 1 > sizeof(un.sun_path)) 193 { 194 ferite_set_error(script, 0, "Path too long"); 195 FE_RETURN_NULL_OBJECT; 196 } 197 memcpy(un.sun_path, path->data, path->length + 1); 198 sa = (struct sockaddr*)&un; 199 200 if(bind(sock, sa, sizeof(struct sockaddr_un))) 201 { 202 ferite_set_error(script, errno, "%s", strerror(errno)); 203 close(sock); 204 FE_RETURN_NULL_OBJECT; 205 } 206 if(listen(sock, 10)) 207 { 208 ferite_set_error(script, errno, "%s", strerror(errno)); 209 close(sock); 210 FE_RETURN_NULL_OBJECT; 211 } 212 if((cls = ferite_find_class(script, script->mainns, "Network.Unix.Stream"))) 213 { 214 args = ferite_create_parameter_list(4); 215 args = ferite_add_to_parameter_list(args, fe_new_lng_static("socket", sock)); 216 obj = ferite_new_object(script, cls, args); 217 ferite_delete_parameter_list(script, args); 218 fv = ferite_create_string_variable(script, "path", path, FE_STATIC); 219 ferite_object_set_var(script, VAO(obj), "path", fv); 220 FE_RETURN_VAR(obj); 221 } 222 close(sock); 223 FE_RETURN_NULL_OBJECT; 224 } 225 } 226 /** @end */ 227} 228/** 229 * @end 230 */