提交 b6c7dd36 authored 作者: Andrew Thompson's avatar Andrew Thompson

Merge in Rob Charlton's patch for outbound session support in mod_erlang_event


git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11376 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 6bc24b8c
BASE=../../../..
LOCAL_SOURCES=handle_msg.c ei_helpers.c
LOCAL_OBJS=handle_msg.o ei_helpers.o
include $(BASE)/build/modmake.rules
LOCAL_CFLAGS=-I/usr/local/lib/erlang/lib/erl_interface-3.5.8/include -L/usr/local/lib/erlang/lib/erl_interface-3.5.8/lib/ -D_REENTRANT
LOCAL_CFLAGS=-I/usr/local/lib/erlang/lib/erl_interface-3.5.9/include -L/usr/local/lib/erlang/lib/erl_interface-3.5.9/lib/ -D_REENTRANT
LOCAL_LDFLAGS=-lei
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
*
* 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 <anthmct@yahoo.com>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Andrew Thompson <andrew@hijacked.us>
* Rob Charlton <rob.charlton@savageminds.com>
*
*
* ei_helpers.c -- helper functions for ei
*
*/
#include <switch.h>
#include <ei.h>
#include "mod_erlang_event.h"
/* Stolen from code added to ei in R12B-5.
* Since not everyone has this version yet;
* provide our own version.
* */
#define put8(s,n) do { \
(s)[0] = (char)((n) & 0xff); \
(s) += 1; \
} while (0)
#define put32be(s,n) do { \
(s)[0] = ((n) >> 24) & 0xff; \
(s)[1] = ((n) >> 16) & 0xff; \
(s)[2] = ((n) >> 8) & 0xff; \
(s)[3] = (n) & 0xff; \
(s) += 4; \
} while (0)
void ei_link(listener_t *listener, erlang_pid *from, erlang_pid *to) {
char msgbuf[2048];
char *s;
int index = 0;
/*int n;*/
index = 5; /* max sizes: */
ei_encode_version(msgbuf,&index); /* 1 */
ei_encode_tuple_header(msgbuf,&index,3);
ei_encode_long(msgbuf,&index,ERL_LINK);
ei_encode_pid(msgbuf,&index,from); /* 268 */
ei_encode_pid(msgbuf,&index,to); /* 268 */
/* 5 byte header missing */
s = msgbuf;
put32be(s, index - 4); /* 4 */
put8(s, ERL_PASS_THROUGH); /* 1 */
/* sum: 542 */
switch_mutex_lock(listener->sock_mutex);
write(listener->sockfd, msgbuf, index);
switch_mutex_unlock(listener->sock_mutex);
}
void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event)
{
int i;
char *uuid = switch_event_get_header(event, "unique-id");
switch_event_header_t *hp;
for (i = 0, hp = event->headers; hp; hp = hp->next, i++);
if (event->body)
i++;
ei_x_encode_list_header(ebuf, i+1);
if (uuid) {
ei_x_encode_string(ebuf, switch_event_get_header(event, "unique-id"));
} else {
ei_x_encode_atom(ebuf, "undefined");
}
for (hp = event->headers; hp; hp = hp->next) {
ei_x_encode_tuple_header(ebuf, 2);
ei_x_encode_string(ebuf, hp->name);
ei_x_encode_string(ebuf, hp->value);
}
if (event->body) {
ei_x_encode_tuple_header(ebuf, 2);
ei_x_encode_string(ebuf, "body");
ei_x_encode_string(ebuf, event->body);
}
ei_x_encode_empty_list(ebuf);
}
void ei_encode_switch_event_tag(ei_x_buff *ebuf, switch_event_t *event, char *tag)
{
ei_x_encode_tuple_header(ebuf, 2);
ei_x_encode_atom(ebuf, tag);
ei_encode_switch_event_headers(ebuf, event);
}
switch_status_t initialise_ei(struct ei_cnode_s *ec)
{
switch_status_t rv;
struct sockaddr_in server_addr;
/* zero out the struct before we use it */
memset(&server_addr, 0, sizeof(server_addr));
/* convert the configured IP to network byte order, handing errors */
rv = inet_pton(AF_INET, prefs.ip, &server_addr.sin_addr.s_addr);
if (rv == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not parse invalid ip address: %s\n", prefs.ip);
return SWITCH_STATUS_FALSE;
} else if (rv == -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error when parsing ip address %s : %s\n", prefs.ip, strerror(errno));
return SWITCH_STATUS_FALSE;
}
/* set the address family and port */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(prefs.port);
struct hostent *nodehost = gethostbyaddr(&server_addr.sin_addr.s_addr, sizeof(server_addr.sin_addr.s_addr), AF_INET);
char *thishostname = nodehost->h_name;
char thisnodename[MAXNODELEN+1];
if (!strcmp(thishostname, "localhost"))
gethostname(thishostname, EI_MAXHOSTNAMELEN);
if (prefs.shortname) {
char *off;
if ((off = strchr(thishostname, '.'))) {
*off = '\0';
}
}
snprintf(thisnodename, MAXNODELEN+1, "%s@%s", prefs.nodename, thishostname);
/* init the ei stuff */
if (ei_connect_xinit(ec, thishostname, prefs.nodename, thisnodename, (Erl_IpAddr)(&server_addr.sin_addr.s_addr), prefs.cookie, 0) < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to init ei connection\n");
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ei initialized at %s\n", thisnodename);
return SWITCH_STATUS_SUCCESS;
}
/* 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:
*/
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
*
* 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 <anthmct@yahoo.com>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* 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_OUTBOUND_INIT = (1 << 0), /* Erlang peer has been notified of this session */
LFLAG_SESSION_ALIVE
} session_flag_t;
struct session_elem {
switch_core_session_t *session;
switch_mutex_t *flag_mutex;
uint32_t flags;
/* registered process name that will receive call notifications from this session */
char* reg_name;
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;
erlang_pid log_pid;
erlang_pid event_pid;
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_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;
erlang_pid pid;
char *registered_process; /* TODO */
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;
};
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;
};
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);
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")
/* mod_erlang_event.c */
session_elem_t* attach_call_to_listener(listener_t* listener, char* reg_name, 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:
*/
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论