diff --git a/monitor.c b/monitor.c index 755de850..bf903592 100644 --- a/monitor.c +++ b/monitor.c @@ -376,7 +376,15 @@ int monitor_process_command(int index,char *cmd) vomp_mdp_event(&mdp,NULL,0); } } - else if (sscanf(cmd,"pickup %x",&callSessionToken)==1) { + else if (sscanf(cmd,"status %x",&callSessionToken)==1) { + int i; + for(i=0;ilocal.last_state=call->local.state; call->remote.last_state=call->remote.state; if (show) { + if (0) WHYF("sending call status to monitor"); snprintf(msg,1024,"CALLSTATUS:%06x:%06x:%d:%d:%s:%s:%s:%s\n", call->local.session,call->remote.session, call->local.state,call->remote.state, diff --git a/overlay_abbreviations.c b/overlay_abbreviations.c index a52d98f0..da4927d3 100644 --- a/overlay_abbreviations.c +++ b/overlay_abbreviations.c @@ -556,3 +556,13 @@ int overlay_abbreviate_set_most_recent_address(unsigned char *in) overlay_render_sid(in)); return 0; } + +int overlay_abbreviate_clear_most_recent_address() +{ + /* make previous address invalid (first byte must be >0x0f to be valid) */ + overlay_abbreviate_previous_address.b[0]=0x00; + + if (debug&DEBUG_OVERLAYABBREVIATIONS) + fprintf(stderr,"Cleared most recent address\n"); + return 0; +} diff --git a/overlay_interface.c b/overlay_interface.c index b7201cbe..8b353474 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -798,7 +798,10 @@ int overlay_tick_interface(int i, long long now) component payloads are all self-authenticating, or at least that is the theory. */ unsigned char bytes[]={/* Magic */ 'O',0x10, /* Version */ 0x00,0x01}; - if (ob_append_bytes(e,bytes,4)) return WHY("ob_append_bytes() refused to append magic bytes."); + if (ob_append_bytes(e,bytes,4)) { + ob_free(e); + return WHY("ob_append_bytes() refused to append magic bytes."); + } /* 1. Send announcement about ourselves, including one SID that we host if we host more than one SID (the first SID we host becomes our own identity, saving a little bit of data here). diff --git a/overlay_mdp.c b/overlay_mdp.c index 1205db70..aed9c9ee 100644 --- a/overlay_mdp.c +++ b/overlay_mdp.c @@ -898,8 +898,10 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP, } int q=OQ_ORDINARY; - if (mdp->out.dst.port==MDP_PORT_VOMP) q=OQ_ISOCHRONOUS_VOICE; - if (overlay_payload_enqueue(OQ_ORDINARY,frame,0)) + if (mdp->out.dst.port==MDP_PORT_VOMP) { + q=OQ_ISOCHRONOUS_VOICE; + } + if (overlay_payload_enqueue(q,frame,0)) { if (frame) op_free(frame); return WHY("Error enqueuing frame"); diff --git a/overlay_payload.c b/overlay_payload.c index fa46c4f9..d97cc423 100644 --- a/overlay_payload.c +++ b/overlay_payload.c @@ -244,7 +244,51 @@ int overlay_payload_enqueue(int q,overlay_frame *p,int forceBroadcastP) Complain if there are too many frames in the queue. */ + if (q==OQ_ISOCHRONOUS_VOICE&&(!forceBroadcastP)) { + /* Dispatch voice data immediately. */ + int interface=-1; + int nexthoplen=SID_SIZE; + overlay_abbreviate_clear_most_recent_address(); + + if (overlay_get_nexthop(p->destination,p->nexthop,&nexthoplen, + &interface)) { + return WHY("Failed to resolve nexthop for voice packet"); + } + if (interface==-1) { + return WHY("Failed to determine interface for sending voice packet"); + } + + overlay_buffer *b=ob_new(overlay_interfaces[interface].mtu); + unsigned char bytes[]={/* Magic */ 'O',0x10, + /* Version */ 0x00,0x01}; + if (ob_append_bytes(b,bytes,4)) { + ob_free(b); + return WHY("ob_append_bytes() refused to append magic bytes."); + } + if (overlay_frame_package_fmt1(p,b)) { + ob_free(b); + return WHY("could not package voice frame for immediate dispatch"); + } + + if (debug&DEBUG_OVERLAYINTERFACES) + WHYF("Sending %d byte voice packet",b->length); + if (!overlay_broadcast_ensemble(interface,NULL,b->bytes,b->length)) + { + overlay_update_sequence_number(); + if (debug&DEBUG_OVERLAYINTERFACES) + WHYF("Voice frame #%lld sent on interface #%d (%d bytes)", + (long long)overlay_sequence_number,interface,b->length); + ob_free(b); + return 0; + } else { + WHYF("Failed to send voice frame on interface #%d (%d bytes)", + interface,b->length); + ob_free(b); + return -1; + } + } + if (q<0||q>=OQ_MAX) return WHY("Invalid queue specified"); if (!p) return WHY("Cannot queue NULL"); @@ -276,22 +320,6 @@ int overlay_payload_enqueue(int q,overlay_frame *p,int forceBroadcastP) if (0) dump_queue("after",q); - if (q==OQ_ISOCHRONOUS_VOICE - ||(overlay_tx[q].length>=(overlay_tx[q].maxLength/2))) - { - /* queues are getting a bit full, so pump some packets out now. - XXX - this is a bit crude, as it should work out which - interfaces need prodding, and also correctly prioritise what - goes into the packet. Also, it should make sure the queue is - not too full after. */ - int i; - long long now=overlay_gettime_ms(); - for(i=0;iscores[*interface]<1) { if (debug&DEBUG_OVERLAYROUTING) + *interface=-1; WHYF("No open path to %s\n",overlay_render_sid(neh->node->sid)); return -1; } diff --git a/serval.h b/serval.h index f636000c..59776cf8 100755 --- a/serval.h +++ b/serval.h @@ -840,6 +840,7 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of int overlay_abbreviate_remember_index(int index_byte_count,unsigned char *in,unsigned char *index_bytes); extern int overlay_abbreviate_repeat_policy; int overlay_abbreviate_set_most_recent_address(unsigned char *in); +int overlay_abbreviate_clear_most_recent_address(); /* Return codes for resolution of abbreviated addressses */ #define OA_UNINITIALISED 0 /* Nothing has been written into the field */ diff --git a/vomp.c b/vomp.c index d93c3bf1..671f6eec 100644 --- a/vomp.c +++ b/vomp.c @@ -602,6 +602,8 @@ int vomp_mdp_event(overlay_mdp_frame *mdp, call->create_time=overlay_gettime_ms(); call->local.state=VOMP_STATE_CALLPREP; call->remote.state=VOMP_STATE_NOCALL; /* far end has yet to agree that a call is happening */ + monitor_call_status(call); + /* allocate unique call session token, which is how the client will refer to this call during its life */ while (!call->local.session) @@ -644,6 +646,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp, "No such call"); if (call->local.state==VOMP_STATE_INCALL) vomp_call_stop_audio(call); call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); overlay_mdp_reply_error(mdp_named_socket, recvaddr,recvaddrlen,0,"Success"); return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_TELLINTERESTED,NULL); @@ -660,6 +663,7 @@ int vomp_mdp_event(overlay_mdp_frame *mdp, "No such call"); if (call->local.state==VOMP_STATE_RINGINGIN) { call->local.state=VOMP_STATE_INCALL; + monitor_call_status(call); call->ringing=0; /* state machine does job of starting audio stream, just tell everyone about the changed state. */ @@ -767,6 +771,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) call->last_activity=overlay_gettime_ms(); call->remote.sequence=sender_seq; call->remote.state=sender_state; + monitor_call_status(call); return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_TELLCODECS,NULL); } else { if (0) WHY("recvr_session!=0, looking for existing call"); @@ -783,15 +788,21 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) { /* No registered listener, so we cannot answer the call, so just reject it. */ - WHYF("Rejecting call due to lack of a listener: states=%d,%d", + if (0) WHYF("Rejecting call due to lack of a listener: states=%d,%d", call->local.state,call->remote.state); call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); if (call->remote.statelocal.state)); + } + /* Consider states: our actual state, sender state, what the sender thinks our state is, and what we think the sender's state is. But largely it breaks down to what we think our state is, and what they think their @@ -799,6 +810,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) int combined_state=call->local.state<<3; combined_state|=sender_state; call->remote.state=sender_state; + monitor_call_status(call); switch(combined_state) { case (VOMP_STATE_NOCALL<<3)|VOMP_STATE_NOCALL: /* We both think that we are not yet in a call, and we have session numbers @@ -828,6 +840,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) until we both have acknowledged this (when I am RINGINGIN and they are RINGINGOUT). */ call->local.state=VOMP_STATE_RINGINGIN; + monitor_call_status(call); vomp_extract_remote_codec_list(call,mdp); break; case (VOMP_STATE_NOCALL<<3)|VOMP_STATE_RINGINGIN: @@ -836,6 +849,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) We just keep persisting, because once they acknowledge this, we will both move to CALLENDED and hang up */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); break; case (VOMP_STATE_NOCALL<<3)|VOMP_STATE_INCALL: /* As above, a call has probably been hung up by us, but the far end has @@ -845,6 +859,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) case (VOMP_STATE_NOCALL<<3)|VOMP_STATE_CALLENDED: /* Far end has given up on the call, so also move to CALLENDED */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); break; case (VOMP_STATE_CALLPREP<<3)|VOMP_STATE_NOCALL: /* We are getting ready to ring, and the other end has issued a session @@ -853,6 +868,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) far end. But we don't start ringing until the far end acknowledges the state change. */ call->local.state=VOMP_STATE_RINGINGOUT; + monitor_call_status(call); vomp_extract_remote_codec_list(call,mdp); break; case (VOMP_STATE_CALLPREP<<3)|VOMP_STATE_CALLPREP: @@ -861,6 +877,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) let's not prevent it. We move to RINGINGOUT (as they probably will as well). */ call->local.state=VOMP_STATE_RINGINGOUT; + monitor_call_status(call); vomp_extract_remote_codec_list(call,mdp); break; case (VOMP_STATE_CALLPREP<<3)|VOMP_STATE_RINGINGOUT: @@ -868,6 +885,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) this seems a very unlikely situation. But the appropriate action is clear: get ready to start ringing. */ call->local.state=VOMP_STATE_RINGINGIN; + monitor_call_status(call); vomp_extract_remote_codec_list(call,mdp); break; case (VOMP_STATE_CALLPREP<<3)|VOMP_STATE_RINGINGIN: @@ -875,6 +893,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) They seem to have guessed our next move, which is fine. We move to RINGINGOUT. */ call->local.state=VOMP_STATE_RINGINGOUT; + monitor_call_status(call); vomp_extract_remote_codec_list(call,mdp); break; case (VOMP_STATE_CALLPREP<<3)|VOMP_STATE_INCALL: @@ -884,16 +903,19 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) can switch to engaged tone by sending a single VOMP_CODEC_ENGAGED audio frame. Call-waiting not currently supported. */ call->local.state=VOMP_STATE_INCALL; + monitor_call_status(call); if (vomp_call_start_audio(call)) call->local.codec=VOMP_CODEC_ENGAGED; break; case (VOMP_STATE_CALLPREP<<3)|VOMP_STATE_CALLENDED: /* far end says no call */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); break; case (VOMP_STATE_RINGINGOUT<<3)|VOMP_STATE_NOCALL: /* We are calling them, and they have not yet answered, wait for synchronisation. */ call->local.state=VOMP_STATE_RINGINGOUT; + monitor_call_status(call); vomp_extract_remote_codec_list(call,mdp); break; case (VOMP_STATE_RINGINGOUT<<3)|VOMP_STATE_CALLPREP: @@ -905,6 +927,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) /* we are each calling each other, so move to INCALL and start audio */ vomp_extract_remote_codec_list(call,mdp); call->local.state=VOMP_STATE_INCALL; + monitor_call_status(call); if (vomp_call_start_audio(call)) call->local.codec=VOMP_CODEC_ENGAGED; break; case (VOMP_STATE_RINGINGOUT<<3)|VOMP_STATE_RINGINGIN: @@ -917,6 +940,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) /* we are calling them, and they have entered the call, so we should enter the call as well. */ call->local.state=VOMP_STATE_INCALL; + monitor_call_status(call); call->ringing=0; if (vomp_call_start_audio(call)) call->local.codec=VOMP_CODEC_ENGAGED; break; @@ -924,10 +948,12 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) /* Other end has rejected call */ vomp_call_rejected(call); call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); break; case (VOMP_STATE_RINGINGIN<<3)|VOMP_STATE_NOCALL: /* we are ringing and they think there is no call, so move to CALLENDED */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); vomp_call_error(call); break; case (VOMP_STATE_RINGINGIN<<3)|VOMP_STATE_CALLPREP: @@ -935,6 +961,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) ringing us. I guess we should stop ringing. Should we also abort the call? */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); vomp_call_error(call); break; case (VOMP_STATE_RINGINGIN<<3)|VOMP_STATE_RINGINGOUT: @@ -945,6 +972,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) case (VOMP_STATE_RINGINGIN<<3)|VOMP_STATE_RINGINGIN: /* er, we both think that the other is calling us. */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); vomp_call_error(call); break; case (VOMP_STATE_RINGINGIN<<3)|VOMP_STATE_INCALL: @@ -956,15 +984,18 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) /* the far end has rejected our attempt to call them */ vomp_call_rejected(call); call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); break; case (VOMP_STATE_INCALL<<3)|VOMP_STATE_NOCALL: /* this shouldn't happen */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); vomp_call_error(call); break; case (VOMP_STATE_INCALL<<3)|VOMP_STATE_CALLPREP: /* this shouldn't happen either */ call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); vomp_call_error(call); break; case (VOMP_STATE_INCALL<<3)|VOMP_STATE_RINGINGOUT: @@ -983,6 +1014,7 @@ int vomp_mdp_received(overlay_mdp_frame *mdp) /* far end hung up */ vomp_call_stop_audio(call); call->local.state=VOMP_STATE_CALLENDED; + monitor_call_status(call); break; case (VOMP_STATE_CALLENDED<<3)|VOMP_STATE_NOCALL: case (VOMP_STATE_CALLENDED<<3)|VOMP_STATE_CALLPREP: @@ -1452,6 +1484,7 @@ int vomp_tick() Keep call structure hanging around for a bit so that we can synchonrise with the far end if possible. */ vomp_call_states[i].local.state=VOMP_STATE_CALLENDED; + monitor_call_status(&vomp_call_states[i]); vomp_send_status(&vomp_call_states[i], VOMP_TELLREMOTE|VOMP_TELLINTERESTED,NULL); vomp_call_states[i].last_activity=now;