232 lines
6.6 KiB
C
232 lines
6.6 KiB
C
/*
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
|
*
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
|
* Andrew Thompson <andrew@hijacked.us>
|
|
* Rob Charlton <rob.charlton@savageminds.com>
|
|
*
|
|
*
|
|
* mod_erlang_event.h -- Erlang Event Handler derived from mod_event_socket
|
|
*
|
|
*/
|
|
|
|
typedef enum {
|
|
LFLAG_WAITING_FOR_PID = (1 << 0), /* waiting for a node to return a pid */
|
|
LFLAG_OUTBOUND_INIT = (1 << 1), /* Erlang peer has been notified of this session */
|
|
LFLAG_SESSION_ALIVE = (1 << 2),
|
|
} session_flag_t;
|
|
|
|
typedef enum {
|
|
ERLANG_PID = 0,
|
|
ERLANG_REG_PROCESS
|
|
} process_type;
|
|
|
|
typedef enum {
|
|
ERLANG_STRING = 0,
|
|
ERLANG_BINARY
|
|
} erlang_encoding_t;
|
|
|
|
struct erlang_process {
|
|
process_type type;
|
|
char *reg_name;
|
|
erlang_pid pid;
|
|
};
|
|
|
|
struct session_elem {
|
|
switch_core_session_t *session;
|
|
switch_mutex_t *flag_mutex;
|
|
uint32_t flags;
|
|
struct erlang_process process;
|
|
switch_queue_t *event_queue;
|
|
struct session_elem *next;
|
|
};
|
|
|
|
typedef struct session_elem session_elem_t;
|
|
|
|
typedef enum {
|
|
LFLAG_RUNNING = (1 << 0),
|
|
LFLAG_EVENTS = (1 << 1),
|
|
LFLAG_LOG = (1 << 2),
|
|
LFLAG_MYEVENTS = (1 << 3),
|
|
LFLAG_STATEFUL = (1 << 4)
|
|
} event_flag_t;
|
|
|
|
/* There is one listener for each Erlang node we are attached to - either
|
|
inbound or outbound. For example, if the erlang node node1@server connects
|
|
to freeswitch then a listener is created and handles commands sent from
|
|
that node. If 5 calls are directed to the outbound erlang application
|
|
via the dialplan, and are also set to talk to node1@server, then those
|
|
5 call sessions will be "attached" to the same listener.
|
|
*/
|
|
struct listener {
|
|
int sockfd;
|
|
struct ei_cnode_s *ec;
|
|
struct erlang_process log_process;
|
|
struct erlang_process event_process;
|
|
char *peer_nodename;
|
|
switch_queue_t *event_queue;
|
|
switch_queue_t *log_queue;
|
|
switch_memory_pool_t *pool;
|
|
switch_mutex_t *flag_mutex;
|
|
switch_mutex_t *sock_mutex;
|
|
char *ebuf;
|
|
uint32_t flags;
|
|
switch_log_level_t level;
|
|
uint8_t event_list[SWITCH_EVENT_ALL + 1];
|
|
switch_hash_t *event_hash;
|
|
switch_hash_t *fetch_reply_hash;
|
|
switch_hash_t *spawn_pid_hash;
|
|
switch_thread_rwlock_t *rwlock;
|
|
switch_mutex_t *session_mutex;
|
|
session_elem_t *session_list;
|
|
int lost_events;
|
|
int lost_logs;
|
|
time_t last_flush;
|
|
uint32_t timeout;
|
|
uint32_t id;
|
|
char remote_ip[50];
|
|
/*switch_port_t remote_port;*/
|
|
struct listener *next;
|
|
};
|
|
|
|
typedef struct listener listener_t;
|
|
|
|
struct erlang_binding {
|
|
switch_xml_section_t section;
|
|
struct erlang_process process;
|
|
listener_t *listener;
|
|
struct erlang_binding *next;
|
|
};
|
|
|
|
struct api_command_struct {
|
|
char *api_cmd;
|
|
char *arg;
|
|
listener_t *listener;
|
|
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
|
uint8_t bg;
|
|
erlang_pid pid;
|
|
switch_memory_pool_t *pool;
|
|
};
|
|
|
|
struct globals_struct {
|
|
switch_mutex_t *listener_mutex;
|
|
switch_event_node_t *node;
|
|
unsigned int reference0;
|
|
unsigned int reference1;
|
|
unsigned int reference2;
|
|
switch_mutex_t *ref_mutex;
|
|
};
|
|
typedef struct globals_struct globals_t;
|
|
|
|
struct listen_list_struct {
|
|
int sockfd;
|
|
switch_mutex_t *sock_mutex;
|
|
listener_t *listeners;
|
|
uint8_t ready;
|
|
};
|
|
typedef struct listen_list_struct listen_list_t;
|
|
|
|
struct bindings_struct {
|
|
struct erlang_binding *head;
|
|
switch_xml_binding_t *search_binding;
|
|
};
|
|
typedef struct bindings_struct bindings_t;
|
|
|
|
#define MAX_ACL 100
|
|
struct prefs_struct {
|
|
switch_mutex_t *mutex;
|
|
char *ip;
|
|
char *nodename;
|
|
switch_bool_t shortname;
|
|
uint16_t port;
|
|
char *cookie;
|
|
int done;
|
|
int threads;
|
|
char *acl[MAX_ACL];
|
|
uint32_t acl_count;
|
|
uint32_t id;
|
|
erlang_encoding_t encoding;
|
|
};
|
|
typedef struct prefs_struct prefs_t;
|
|
|
|
/* shared globals */
|
|
#ifdef DEFINE_GLOBALS
|
|
globals_t globals;
|
|
listen_list_t listen_list;
|
|
bindings_t bindings;
|
|
prefs_t prefs;
|
|
#else
|
|
extern globals_t globals;
|
|
extern listen_list_t listen_list;
|
|
extern bindings_t bindings;
|
|
extern prefs_t prefs;
|
|
#endif
|
|
|
|
/* function prototypes */
|
|
/* handle_msg.c */
|
|
int handle_msg(listener_t *listener, erlang_msg *msg, ei_x_buff *buf, ei_x_buff *rbuf);
|
|
|
|
/* ei_helpers.c */
|
|
void ei_link(listener_t *listener, erlang_pid *from, erlang_pid *to);
|
|
void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event);
|
|
void ei_encode_switch_event_tag(ei_x_buff *ebuf, switch_event_t *event, char *tag);
|
|
int ei_pid_from_rpc(struct ei_cnode_s *ec, int sockfd, erlang_ref *ref, char *module, char *function);
|
|
int ei_spawn(struct ei_cnode_s *ec, int sockfd, erlang_ref *ref, char *module, char *function, int argc, char **argv);
|
|
void ei_init_ref(struct ei_cnode_s *ec, erlang_ref *ref);
|
|
void ei_x_print_reg_msg(ei_x_buff *buf, char *dest, int send);
|
|
void ei_x_print_msg(ei_x_buff *buf, erlang_pid *pid, int send);
|
|
int ei_sendto(ei_cnode *ec, int fd, struct erlang_process *process, ei_x_buff *buf);
|
|
void ei_hash_ref(erlang_ref *ref, char *output);
|
|
int ei_compare_pids(erlang_pid *pid1, erlang_pid *pid2);
|
|
int ei_decode_string_or_binary(char *buf, int *index, int maxlen, char *dst);
|
|
switch_status_t initialise_ei(struct ei_cnode_s *ec);
|
|
#define ei_encode_switch_event(_b, _e) ei_encode_switch_event_tag(_b, _e, "event")
|
|
|
|
/* crazy macro for toggling encoding type */
|
|
#define _ei_x_encode_string(buf, string) switch (prefs.encoding) { \
|
|
case ERLANG_BINARY: \
|
|
ei_x_encode_binary(buf, string, strlen(string)); \
|
|
break; \
|
|
default: \
|
|
ei_x_encode_string(buf, string); \
|
|
break; \
|
|
}
|
|
|
|
/* mod_erlang_event.c */
|
|
session_elem_t* attach_call_to_registered_process(listener_t* listener, char* reg_name, switch_core_session_t *session);
|
|
session_elem_t* attach_call_to_pid(listener_t* listener, erlang_pid* pid, switch_core_session_t *session);
|
|
session_elem_t* attach_call_to_spawned_process(listener_t* listener, char *module, char *function, switch_core_session_t *session);
|
|
|
|
/* For Emacs:
|
|
* Local Variables:
|
|
* mode:c
|
|
* indent-tabs-mode:t
|
|
* tab-width:4
|
|
* c-basic-offset:4
|
|
* End:
|
|
* For VIM:
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
|
*/
|