17 #include <sipwitch-config.h>
18 #include <ucommon/ucommon.h>
19 #include <ucommon/export.h>
25 #if !defined(_MSWINDOWS_)
36 static mutex_t private_locking;
37 static bool shutdown_flag =
false;
39 static struct sockaddr_in ipc_addr;
41 static struct sockaddr_un ipc_addr;
43 static socket_t ipc_socket = INVALID_SOCKET;
52 void assign(socket_t so);
55 static void add(socket_t so);
56 static void stop(
events *message);
57 static void send(
events *message);
62 static string_t saved_state(
"up"),
saved_realm(
"unknown");
63 static time_t started;
95 private_locking.acquire();
98 freelist = (
dispatch *)node->getNext();
103 private_locking.release();
108 private_locking.acquire();
109 linked_pointer<dispatch> dp = root;
113 ::send(dp->session, (
const char *)msg,
sizeof(
events), 0);
114 ::close(dp->session);
119 private_locking.release();
125 struct timeval timeout;
126 if(ipc_socket == INVALID_SOCKET)
129 private_locking.acquire();
130 linked_pointer<dispatch> dp = root;
134 if(::
send(dp->session, (
const char *)msg,
sizeof(
events), 0) < (ssize_t)
sizeof(
events)) {
136 shell::log(
DEBUG3,
"releasing client events for %ld", (
long)dp->session);
142 memset(&timeout, 0,
sizeof(timeout));
143 memset(&detect, 0,
sizeof(detect));
144 FD_SET(dp->session, &detect);
145 if(select(dp->session + 1, &detect, NULL, &detect, &timeout) > 0)
149 private_locking.release();
156 void event_thread::run(
void)
163 shell::log(
DEBUG1,
"starting event dispatcher");
164 shutdown_flag =
false;
168 client = ::accept(ipc_socket, NULL, NULL);
170 if(ipc_socket != INVALID_SOCKET) {
171 Socket::release(ipc_socket);
172 ipc_socket = INVALID_SOCKET;
177 shell::log(shell::ERR,
"event accept failed; error=%ld", (
long)client);
182 shell::log(
DEBUG3,
"connecting client events for %ld", (
long)client);
185 evt.msg.server.started = started;
186 String::set(evt.msg.server.version,
sizeof(evt.msg.server.version), VERSION);
187 private_locking.acquire();
188 String::set(evt.msg.server.state,
sizeof(evt.msg.server.state), *saved_state);
189 String::set(evt.msg.server.realm,
sizeof(evt.msg.server.realm), *
saved_realm);
190 private_locking.release();
191 ::send(client, (
const char *)&evt,
sizeof(evt), 0);
195 ::send(client, (
const char *)&evt,
sizeof(evt), 0);
200 shell::log(
DEBUG1,
"stopping event dispatcher");
205 if(ipc_socket != INVALID_SOCKET)
209 ipc_socket = ::socket(AF_INET, SOCK_STREAM, 0);
211 ipc_socket = ::socket(AF_UNIX, SOCK_STREAM, 0);
214 if(ipc_socket == INVALID_SOCKET)
217 memset(&ipc_addr, 0,
sizeof(ipc_addr));
223 ipc_addr.sin_family = AF_INET;
224 ipc_addr.sin_addr.s_addr = inet_addr(
"127.0.0.1");
225 ipc_addr.sin_port = 0;
226 if(::bind(ipc_socket, (
struct sockaddr *)&ipc_addr,
sizeof(ipc_addr)) < 0)
229 alen =
sizeof(ipc_addr);
230 ::getsockname(ipc_socket, (
struct sockaddr *)&ipc_addr, &alen);
231 port = ntohs(ipc_addr.sin_port);
232 keys = HKEY_LOCAL_MACHINE;
233 if(RegCreateKeyEx(keys,
"SOFTWARE\\sipwitch", 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &subkey, NULL) == ERROR_SUCCESS) {
234 RegSetValueEx(subkey,
"port", 0L, REG_DWORD, (
const BYTE *)&port,
sizeof(port));
235 port = GetCurrentProcessId();
236 RegSetValueEx(subkey,
"pid", 0L, REG_DWORD, (
const BYTE *)&port,
sizeof(port));
240 ipc_addr.sun_family = AF_UNIX;
241 String::set(ipc_addr.sun_path,
sizeof(ipc_addr.sun_path),
control::env(
"events"));
244 if(::bind(ipc_socket, (
struct sockaddr *)&ipc_addr, SUN_LEN(&ipc_addr)) < 0)
248 if(::listen(ipc_socket, 10) < 0)
255 Socket::release(ipc_socket);
256 ipc_socket = INVALID_SOCKET;
308 private_locking.acquire();
310 private_locking.release();
320 private_locking.acquire();
322 private_locking.release();
324 String::set(evt.msg.server.state,
sizeof(evt.msg.server.state), str);
374 string_t
uri = str(
"sip:") + (
const char *)addr;
385 string_t
uri = str(
"sip:") + addr;
394 if(shutdown_flag || ipc_socket == INVALID_SOCKET)
397 shutdown_flag =
true;
404 tmp = ::socket(AF_INET, SOCK_STREAM, 0);
405 ::connect(tmp, (
struct sockaddr *)&ipc_addr,
sizeof(ipc_addr));
407 tmp = ::socket(AF_UNIX, SOCK_STREAM, 0);
408 ::connect(tmp, (
struct sockaddr *)&ipc_addr, SUN_LEN(&ipc_addr));
410 Socket::release(tmp);
static void activate(MappedRegistry *user)
Send event for first instance of user registration.
Some convenience methods for manipulating SIP uri's.
static void failure(const char *reason)
Send error to user.
static volatile char * sip_publish
struct sipwitch::events::@1::@3 user
Event message and supporting methods for plugins.
Representation of a mapped active user record.
time_t starting
Time the call was received.
static void publish(const char *address)
Update publish address...
struct sipwitch::events::@1::@4 server
Definitions for memory mapped objects that may be shared between processes.
char reason[16]
Reason the call was terminated.
static void terminate(const char *reason)
Notify server termination.
static void notice(const char *reason)
Send notice to user.
static string_t saved_realm("unknown")
Stream events to local clients.
static void reload(void)
Refresh clients with any config events...
static bool start(void)
Start server event system by binding event session listener.
static void send(events *message)
type_t type
Type of event message.
static void warning(const char *reason)
Send warning to user.
char dialed[MAX_IDENT_SIZE]
Destination requested on our switch.
static string_t getContact(void)
char display[MAX_DISPLAY_SIZE]
Display name of calling party.
Service configuration and component callbacks.
char ident[MAX_IDENT_SIZE]
Ident of calling parting.
struct sipwitch::events::@1::@2 call
static void release(MappedRegistry *user)
Send event for last instance of user expired or de-registering.
static void add(socket_t so)
Manage control interface.
static void sync(unsigned period=0l)
Test connection and housekeeping notification.
Interface class for call detail records.
union sipwitch::events::@1 msg
Content of message, based on type.
static void drop(cdr *rec)
Send call disconnected event to clients from cdr stop record.
static const char * env(const char *id)
Return the value of a server environment variable.
static void stop(events *message)
static void connect(cdr *rec)
Send call connection to clients from cdr start record.
char network[MAX_NETWORK_SIZE *2]
Subnet interface the caller appeared on.