freeswitch/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h

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:
*/