fixes, screen in and out works, fixed release problem in mISDNuser
[lcr.git] / action.cpp
index b77d937..0bb68cd 100644 (file)
@@ -67,44 +67,96 @@ char *numberrize_callerinfo(char *string, int ntype)
 
 
 /*
- * process init 'internal' / 'external' / 'chan' / 'vbox-record' / 'partyline'...
+ * process init 'internal' / 'external' / 'remote' / 'vbox-record' / 'partyline'...
  */
-void EndpointAppPBX::_action_init_call(int chan)
+void EndpointAppPBX::_action_init_call(char *remote)
 {
-       class Call              *call;
+       class Join              *join;
        struct port_list        *portlist = ea_endpoint->ep_portlist;
+       struct admin_list       *admin;
 
        /* a created call, this should never happen */
-       if (ea_endpoint->ep_call_id)
+       if (ea_endpoint->ep_join_id)
        {
                if (options.deb & DEBUG_EPOINT)
                        PERROR("EPOINT(%d): We already have a call instance, this should never happen!\n", ea_endpoint->ep_serial);
                return;
        }
 
-       /* create call */
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial);
-       if (chan)
-               call = new CallChan(ea_endpoint);
-       else
-               call = new CallPBX(ea_endpoint);
-       if (!call)
+       /* create join */
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new join instance.\n", ea_endpoint->ep_serial);
+       if (remote)
        {
-               /* resource not available */
-               message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
-               new_state(EPOINT_STATE_OUT_DISCONNECT);
-               set_tone(portlist,"cause_22");
-               return;
+               admin = admin_first;
+               while(admin)
+               {
+                       if (admin->remote_name[0] && !strcmp(admin->remote_name, remote))
+                               break;
+                       admin = admin->next;
+               }
+               if (!admin)
+               {
+                       /* resource not available */
+                       trace_header("ACTION remote (not available)", DIRECTION_NONE);
+                       add_trace("application", NULL, "%s", remote);
+                       end_trace();
+                       message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+                       new_state(EPOINT_STATE_OUT_DISCONNECT);
+                       set_tone(portlist,"cause_22");
+                       return;
+               }
+               join = new JoinRemote(ea_endpoint->ep_serial, remote, admin->sock);
        }
-       ea_endpoint->ep_call_id = call->c_serial;
+       else
+               join = new JoinPBX(ea_endpoint);
+       if (!join)
+               FATAL("No memoy for Join instance.\n");
+       ea_endpoint->ep_join_id = join->j_serial;
 }
 void EndpointAppPBX::action_init_call(void)
 {
-       _action_init_call(0);
+       _action_init_call(NULL);
 }
-void EndpointAppPBX::action_init_chan(void)
+void EndpointAppPBX::action_init_remote(void)
 {
-       _action_init_call(1);
+       struct route_param      *rparam;
+       struct port_list        *portlist = ea_endpoint->ep_portlist;
+       struct message          *message;
+       struct capa_info        capainfo;
+       struct caller_info      callerinfo;
+       struct redir_info       redirinfo;
+       struct dialing_info     dialinginfo;
+       char remote[32];
+
+       if (!(rparam = routeparam(e_action, PARAM_APPLICATION)))
+       {
+               trace_header("ACTION remote (no application given)", DIRECTION_NONE);
+               end_trace();
+               new_state(EPOINT_STATE_OUT_DISCONNECT);
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               set_tone(portlist, "cause_3f");
+               return;
+       }
+       SCPY(remote, rparam->string_value);
+       _action_init_call(remote);
+
+       /* create bearer/caller/dialinginfo */
+       memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
+       memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
+       memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
+       memset(&dialinginfo, 0, sizeof(dialinginfo));
+
+       /* send setup to remote */
+       trace_header("ACTION remote (setup)", DIRECTION_NONE);
+       add_trace("number", NULL, dialinginfo.id);
+       add_trace("remote", NULL, remote);
+       end_trace();
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
+       memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
+       memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
+       memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
+       memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
+       message_put(message);
 }
 
 /*
@@ -125,7 +177,7 @@ void EndpointAppPBX::action_dialing_internal(void)
        set_tone(portlist, "proceeding");
        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        new_state(EPOINT_STATE_IN_PROCEEDING);
 
        /* create bearer/caller/dialinginfo */
@@ -184,6 +236,7 @@ void EndpointAppPBX::action_dialing_internal(void)
                trace_header("ACTION extension (extension doesn't exist)", DIRECTION_NONE);
                add_trace("extension", NULL, dialinginfo.id);
                end_trace();
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
                set_tone(portlist, "cause_86");
@@ -196,6 +249,7 @@ void EndpointAppPBX::action_dialing_internal(void)
                add_trace("extension", NULL, dialinginfo.id);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
                message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
                set_tone(portlist, "cause_81");
                return;
@@ -205,7 +259,7 @@ void EndpointAppPBX::action_dialing_internal(void)
        trace_header("ACTION extension (calling)", DIRECTION_NONE);
        add_trace("extension", NULL, dialinginfo.id);
        end_trace();
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
        memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
        memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
        memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
@@ -330,7 +384,7 @@ void EndpointAppPBX::action_dialing_external(void)
        {
                trace_header("ACTION extern (calling denied)", DIRECTION_NONE);
                end_trace();
-               release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
                set_tone(portlist, "cause_82");
                denied:
                message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
@@ -347,7 +401,7 @@ void EndpointAppPBX::action_dialing_external(void)
                {
                        trace_header("ACTION extern (national calls denied)", DIRECTION_NONE);
                        end_trace();
-                       release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
+                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
                        set_tone(portlist, "cause_83");
                        goto denied;
                }
@@ -361,7 +415,7 @@ void EndpointAppPBX::action_dialing_external(void)
                {
                        trace_header("ACTION extern (international calls denied)", DIRECTION_NONE);
                        end_trace();
-                       release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
+                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
                        set_tone(portlist, "cause_84");
                        goto denied;
                }
@@ -373,7 +427,7 @@ void EndpointAppPBX::action_dialing_external(void)
        if (dialinginfo.interfaces[0])
                add_trace("interfaces", NULL, dialinginfo.interfaces);
        end_trace();
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
        memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
        memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
        memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
@@ -382,15 +436,25 @@ void EndpointAppPBX::action_dialing_external(void)
 }
 
 
-void EndpointAppPBX::action_dialing_chan(void)
+void EndpointAppPBX::action_dialing_remote(void)
 {
-       struct port_list *portlist = ea_endpoint->ep_portlist;
+       struct message *message;
+       struct dialing_info dialinginfo;
+//     struct route_param *rparam;
 
-       trace_header("ACTION channel (not implemented)", DIRECTION_NONE);
-       end_trace();
-       message_disconnect_port(portlist, CAUSE_UNIMPLEMENTED, LOCATION_PRIVATE_LOCAL, "");
-       new_state(EPOINT_STATE_OUT_DISCONNECT);
-       set_tone(portlist,"cause_4f");
+       /* create bearer/caller/dialinginfo */
+       memset(&dialinginfo, 0, sizeof(dialinginfo));
+
+       if (dialinginfo.id[0])
+       {
+               /* add or update outgoing call */
+               trace_header("ACTION remote (dialing)", DIRECTION_NONE);
+               add_trace("number", NULL, dialinginfo.id);
+               end_trace();
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_INFORMATION);
+               memcpy(&message->param.information, &dialinginfo, sizeof(struct dialing_info));
+               message_put(message);
+       }
 }
 
 
@@ -445,7 +509,7 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
        set_tone(portlist, "proceeding");
        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        new_state(EPOINT_STATE_IN_PROCEEDING);
 
        memset(&dialinginfo, 0, sizeof(dialinginfo));
@@ -465,7 +529,7 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
        trace_header("ACTION vbox-record (calling)", DIRECTION_NONE);
        add_trace("extension", NULL, "%s", dialinginfo.id);
        end_trace();
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
        memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
        memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
        memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
@@ -479,13 +543,13 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
  */
 void EndpointAppPBX::action_init_partyline(void)
 {
-       class Call *call;
-       class CallPBX *callpbx;
+       class Join *join;
+       class JoinPBX *joinpbx;
        struct port_list *portlist = ea_endpoint->ep_portlist;
        struct message *message;
        struct route_param *rparam;
-       int partyline;
-       struct call_relation *relation;
+       int partyline, jingle = 0;
+       struct join_relation *relation;
 
        portlist = ea_endpoint->ep_portlist;
 
@@ -509,37 +573,33 @@ void EndpointAppPBX::action_init_partyline(void)
                goto noroom;
        }
        partyline = rparam->integer_value;
+       if ((rparam = routeparam(e_action, PARAM_JINGLE)))
+               jingle = 1;
 
-       /* don't create call if partyline exists */
-       call = call_first;
-       while(call)
+       /* don't create join if partyline exists */
+       join = join_first;
+       while(join)
        {
-               if (call->c_type == CALL_TYPE_PBX)
+               if (join->j_type == JOIN_TYPE_PBX)
                {
-                       callpbx = (class CallPBX *)call;
-                       if (callpbx->c_partyline == rparam->integer_value)
+                       joinpbx = (class JoinPBX *)join;
+                       if (joinpbx->j_partyline == partyline)
                                break;
                }
-               call = call->next;
+               join = join->next;
        }
-       if (!call)
+       if (!join)
        {
-               /* create call */
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial);
-               if (!(call = new CallPBX(ea_endpoint)))
-               {
-                       PERROR("no memory for call, exitting");
-                       exit(-1);
-               }
+               /* create join */
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new join instance.\n", ea_endpoint->ep_serial);
+               if (!(join = new JoinPBX(ea_endpoint)))
+                       FATAL("No memory for join object\n");
        } else
        {
-//NOTE: callpbx must be set here
-               /* add relation to existing call */
-               if (!(relation=callpbx->add_relation()))
-               {
-                       PERROR("no memory for call relation, exitting");
-                       exit(-1);
-               }
+//NOTE: joinpbx must be set here
+               /* add relation to existing join */
+               if (!(relation=joinpbx->add_relation()))
+                       FATAL("No memory for join relation\n");
                relation->type = RELATION_TYPE_SETUP;
                relation->channel_state = CHANNEL_STATE_CONNECT;
                relation->rx_state = NOTIFY_STATE_ACTIVE;
@@ -547,20 +607,22 @@ void EndpointAppPBX::action_init_partyline(void)
                relation->epoint_id = ea_endpoint->ep_serial;
 
        }
-       ea_endpoint->ep_call_id = call->c_serial;
+       ea_endpoint->ep_join_id = join->j_serial;
 
        set_tone(portlist, "proceeding");
        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        new_state(EPOINT_STATE_IN_PROCEEDING);
 
-       /* send setup to call */
+       /* send setup to join */
        trace_header("ACTION partyline (calling)", DIRECTION_NONE);
        add_trace("room", NULL, "%d", partyline);
+       add_trace("jingle", NULL, (jingle)?"on":"off");
        end_trace();
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
        message->param.setup.partyline = partyline;
+       message->param.setup.partyline_jingle = jingle;
        memcpy(&message->param.setup.dialinginfo, &e_dialinginfo, sizeof(struct dialing_info));
        memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
        memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
@@ -574,44 +636,8 @@ void EndpointAppPBX::action_init_partyline(void)
  */
 void EndpointAppPBX::action_hangup_call(void)
 {
-       int i;
-
        trace_header("ACTION hangup", DIRECTION_NONE);
        end_trace();
-       /* check */
-       if (e_ext.number[0] == '\0')
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because caller is unknown (not internal).\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id);
-               return;
-       }
-       if (!(read_extension(&e_ext, e_ext.number)))
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because cannot read settings.\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id);
-               return;
-       }
-       if (e_dialinginfo.id[0] == '\0')
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number because nothing was dialed.\n", ea_endpoint->ep_serial, e_ext.number);
-               return;
-       }
-       if (!strcmp(e_dialinginfo.id, e_ext.last_out[0]))
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id);
-               return;
-       }
-
-       /* insert */
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last number '%s'.\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id);
-       i = MAX_REMEMBER-1;
-       while(i)
-       {
-               UCPY(e_ext.last_out[i], e_ext.last_out[i-1]);
-               i--;
-       }
-       SCPY(e_ext.last_out[0], e_dialinginfo.id);
-
-       /* write extension */
-       write_extension(&e_ext, e_ext.number);
 }
 
 
@@ -672,12 +698,12 @@ void EndpointAppPBX::action_dialing_login(void)
                message->param.connectinfo.present = INFO_PRESENT_RESTRICTED;
        else    message->param.connectinfo.present = e_ext.callerid_present;
        /* handle restricted caller ids */
-       apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
+       apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
        /* display callerid if desired for extension */
        SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
        message->param.connectinfo.ntype = e_ext.callerid_type;
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
 
        /* set our caller id */
        SCPY(e_callerinfo.id, e_ext.callerid);
@@ -1041,7 +1067,7 @@ void EndpointAppPBX::_action_redial_reply(int in)
                SPRINT(message->param.notifyinfo.display, "(%d) %s", e_select+1, (last[0])?last:"- empty -");
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s sending display:%s\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display);
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
 }
 
 /* process dialing redial
@@ -1114,7 +1140,7 @@ void EndpointAppPBX::action_dialing_powerdial(void)
        memset(&e_connectinfo, 0, sizeof(e_connectinfo));
        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
 
        /* do dialing */
        SCPY(e_dialinginfo.id, e_ext.last_out[0]);
@@ -1315,7 +1341,7 @@ void EndpointAppPBX::action_dialing_test(void)
                set_tone(portlist, "proceeding");
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                break;
                
                case '2':
@@ -1326,7 +1352,7 @@ void EndpointAppPBX::action_dialing_test(void)
                set_tone(portlist, "ringpbx");
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                break;
                
                case '3':
@@ -1347,11 +1373,11 @@ void EndpointAppPBX::action_dialing_test(void)
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
                memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
                /* handle restricted caller ids */
-               apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
+               apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
                /* display callerid if desired for extension */
                SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
 
                port = find_port_id(portlist->port_id);
                if (port)
@@ -1370,7 +1396,7 @@ void EndpointAppPBX::action_dialing_test(void)
                memset(&e_connectinfo, 0, sizeof(e_connectinfo));
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                set_tone(portlist, "test");
                break;
                
@@ -1384,7 +1410,7 @@ void EndpointAppPBX::action_dialing_test(void)
                memset(&e_connectinfo, 0, sizeof(e_connectinfo));
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                set_tone(portlist, "hold");
                break;
                
@@ -1406,7 +1432,7 @@ void EndpointAppPBX::action_dialing_test(void)
                memset(&e_connectinfo, 0, sizeof(e_connectinfo));
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                set_tone(portlist, causestr);
                break;
                
@@ -1453,7 +1479,7 @@ void EndpointAppPBX::action_dialing_test(void)
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
                memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(message->param.connectinfo));
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                set_tone(portlist, "hold");
                break;
        }
@@ -1746,7 +1772,7 @@ void EndpointAppPBX::action_dialing_calculator(void)
        SPRINT(message->param.notifyinfo.display, ">%s", e_extdialing);
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s' internal values: %f %f\n", ea_endpoint->ep_serial, e_ext.number, e_extdialing, value1, value2);
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
 
 }
 
@@ -1799,7 +1825,7 @@ void EndpointAppPBX::_action_goto_menu(int mode)
        } else
        {
                /* remove digits that are required to match the rule */
-               if (!(rparam = routeparam(e_action, PARAM_STRIP)))
+               if ((rparam = routeparam(e_action, PARAM_STRIP)))
                {
                        if (e_extdialing)
                                SCPY(e_dialinginfo.id, e_extdialing);
@@ -1900,7 +1926,7 @@ void EndpointAppPBX::action_dialing_disconnect(void)
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
                SCPY(message->param.notifyinfo.display, display);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
        }
        e_action = NULL;
 }
@@ -1982,7 +2008,7 @@ nesting?:
        SPRINT(message->param.notifyinfo.display, ">%s %s%s%s", numbering->prefix, numb_actions[numbering->action], (numbering->param[0])?" ":"", numbering->param);
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' sending display:%s\n", ea_endpoint->ep_serial, e_ext.number, numb_actions[numbering->action], message->param.notifyinfo.display);
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, message->paramea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
 #endif
 }
 
@@ -2106,7 +2132,7 @@ void EndpointAppPBX::action_init_pick(void)
        if (extensions) if (extensions[0])
                add_trace("extensions", NULL, "%s", extensions);
        end_trace();
-       pick_call(extensions);
+       pick_join(extensions);
 }
 
 
@@ -2232,7 +2258,7 @@ void EndpointAppPBX::process_dialing(void)
                        release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
                        goto end;
                }
-               release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, 0);
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
                e_action = e_action->next;
                if (!e_action)
                {
@@ -2281,7 +2307,7 @@ void EndpointAppPBX::process_dialing(void)
                                        SCPY(message->param.notifyinfo.display,get_isdn_cause(LOCATION_PRIVATE_LOCAL, epoint->e_ext.display_cause, param->disconnectinfo.location, param->disconnectinfo.cause));
                                }
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, message->param, portlist->port_id, DIRECTION_OUT);
                }
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                set_tone(portlist,"cause_1c");
@@ -2312,10 +2338,10 @@ void EndpointAppPBX::process_dialing(void)
                        goto process_action;
                }
                /* check for chan call */
-               if (!strncmp(e_dialinginfo.id, "chan:", 5))
+               if (!strncmp(e_dialinginfo.id, "remote:", 7))
                {
-                       e_extdialing = e_dialinginfo.id+4;
-                       e_action = &action_chan;
+                       e_extdialing = e_dialinginfo.id+7;
+                       e_action = &action_remote;
                        goto process_action;
                }
                /* check for vbox call */
@@ -2391,7 +2417,7 @@ void EndpointAppPBX::process_dialing(void)
                        memset(&e_connectinfo, 0, sizeof(e_connectinfo));
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                } else
                if ((rparam = routeparam(e_action, PARAM_ALERTING)))
                {
@@ -2399,7 +2425,7 @@ void EndpointAppPBX::process_dialing(void)
                        memset(&e_connectinfo, 0, sizeof(e_connectinfo));
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                } else
                if ((rparam = routeparam(e_action, PARAM_PROCEEDING)))
                {
@@ -2407,7 +2433,7 @@ void EndpointAppPBX::process_dialing(void)
                        memset(&e_connectinfo, 0, sizeof(e_connectinfo));
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                }
 
                if (action_defs[e_action->index].init_func)
@@ -2462,7 +2488,7 @@ void EndpointAppPBX::process_dialing(void)
 
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s'\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        }
 
 end:
@@ -2518,6 +2544,7 @@ void EndpointAppPBX::process_hangup(int cause, int location)
                write_log(e_ext.number, callertext, dialingtext, e_start, e_stop, 0, cause, location);
 
                /* store last received call for reply-list */
+               if (e_origin == 1) // outgoing to phone is incomming for user
                if (e_callerinfo.id[0] || e_callerinfo.extension[0])
                if (e_ext.anon_ignore || e_callerinfo.present!=INFO_PRESENT_RESTRICTED)
                {
@@ -2539,8 +2566,26 @@ void EndpointAppPBX::process_hangup(int cause, int location)
                        } else
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last received id '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_ext.number, callertext);
                }
-       }
 
+               /* store last made call for reply-list */
+               if (e_origin == 0) // incomming from phone is outgoing for user
+               if (e_dialinginfo.id[0])
+               {
+                       if (!!strcmp(e_dialinginfo.id, e_ext.last_out[0]))
+                       {
+                               i = MAX_REMEMBER-1;
+                               while(i)
+                               {
+                                       UCPY(e_ext.last_out[i], e_ext.last_out[i-1]);
+                                       i--;
+                               }
+                               SCPY(e_ext.last_out[0], e_dialinginfo.id);
+                               writeext |= 1; /* store extension later */
+                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last number '%s'.\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id);
+                       } else
+                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last number '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id);
+               }
+       }
        /* write extension if needed */
        if (writeext == 0x11)
                write_extension(&e_ext, e_ext.number);