[Nice] integrating nice to another project

Andrés Suero kaneda.uy at gmail.com
Fri Aug 17 17:32:54 PDT 2012


I attach part of my code, please tell us if you see something fishy.

Thanks again,
Andrés Suero

On Fri, Aug 17, 2012 at 9:16 PM, Andrés Suero <kaneda.uy at gmail.com> wrote:

> Long time Youness,
> I have another question, Is there an easy way to add a g_io_channel as
> source and receiver of data of an agent?
>
> Thanks a lot,
> Andrés Suero
>
>
> On Wed, May 23, 2012 at 10:37 AM, Andrés Suero <kaneda.uy at gmail.com>wrote:
>
>> Thanks a lot for your help Youness!
>>
>>
>> On Tue, May 22, 2012 at 9:54 PM, Youness Alaoui <
>> youness.alaoui at collabora.co.uk> wrote:
>>
>>> Libnice is indeed thread safe, but you have no reason to be using a
>>> thread.
>>> Libnice also requires you to be running the mainloop, otherwise it won't
>>> work,
>>> so make sure to run the mainloop, as for your socket, just add a GSource
>>> on a
>>> g_io_channel on your socket.
>>>
>>> On 05/20/2012 04:28 PM, Andrés Suero wrote:
>>> > Youness,
>>> > Thanks for your response, what we have is a socket that bring us the
>>> information, then we transfer peer to peer with libnice, and another socket
>>> where we need to put the info that we receive from the peer to peer
>>> connection.
>>> > The issue is that the info that we need to transfer to the other peer
>>> is not given all in one call, we need to check is theres info in the socket
>>> time to time to see if theres more, and if it is, we need to send it.
>>> > Is there a way to add a signal to be called in some period of time in
>>> the future, so we can check if we have new info to transmit, or some other
>>> way to get this effect?
>>> > The other (complicated) way that I thought was to start a thread when
>>> we receive the READY state and within this thread call to receive data from
>>> the socket and call to sendit peer to peer, but I don't know if this is
>>> going to crash all over the place because the call to the libnice to send
>>> is going to be from another thread.
>>> >
>>> > Another question, Is there a way to attach a function to a signal with
>>> a context? this way I don't need to have a lot of global variables.
>>> >
>>> > Attached is an example of our code.
>>> >
>>> > Thanks,
>>> > Andrés Suero.
>>> >
>>> >
>>> >
>>> >
>>> > On 5/19/2012 5:16 PM, Youness Alaoui wrote:
>>> >> Hi,
>>> >>
>>> >> I'm not exactly sure why you're doing this, libnice is meant to
>>> create peer to
>>> >> peer connections, it's not meant to be used on a server that proxies
>>> data
>>> >> between two peers.
>>> >> Either way, no, the component_state_changed only gets fired when the
>>> state of
>>> >> the agent changes, so once it goes into READY, it won't get fired
>>> again. You
>>> >> should start your own proxying system only after the state goes to
>>> READY.
>>> >>
>>> >> Hope that helps,
>>> >> Youness
>>> >>
>>> >> On 05/18/2012 11:08 PM, Federico Kouyoumdjian wrote:
>>> >>> We are trying to integrate nice to another project.
>>> >>>
>>> >>> We have a socket in which we read data when the state of nice is
>>> >>> NICE_COMPONENT_STATE_READY. Then we send the data read in the socket
>>> to another
>>> >>> nice agent with the function nice_agent_send.
>>> >>>
>>> >>> Our doubt is what happens if no data is available in the sockt to
>>> send. If we
>>> >>> don't call the function nice_agent_send (because there is no data
>>> available to
>>> >>> send) can we count that cb_component_state_changed will fire again
>>> with the
>>> >>> state NICE_COMPONENT_STATE_READY.
>>> >>>
>>> >>> Thanks for the help.
>>> >>> _______________________________________________
>>> >>> nice mailing list
>>> >>> nice at lists.freedesktop.org
>>> >>> http://lists.freedesktop.org/mailman/listinfo/nice
>>> >>
>>> >>
>>> >> _______________________________________________
>>> >> nice mailing list
>>> >> nice at lists.freedesktop.org
>>> >> http://lists.freedesktop.org/mailman/listinfo/nice
>>> >
>>> >
>>> > _______________________________________________
>>> > nice mailing list
>>> > nice at lists.freedesktop.org
>>> > http://lists.freedesktop.org/mailman/listinfo/nice
>>>
>>>
>>>
>>> _______________________________________________
>>> nice mailing list
>>> nice at lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/nice
>>>
>>>
>>
>>
>> --
>> La información transmitida es sólo para la persona o entidad a la cual
>> está
>> dirigida y puede contener material privilegiado y/o confidencial. Está
>> prohibida cualquier revisión, retransmisión, difusión o cualquier otro uso
>> de esta información, o la realización de cualquier acto en base a esta
>> información por personas o entidades diferentes a las originalmente
>> dirigidas. Si ha recibido esta información por error, por favor, póngase
>> en
>> contacto con el remitente y elimine el material de cualquier computadora.
>> Muchas gracias.
>>
>> The information transmitted is intended only for the person or entity to
>> which it is addressed and may contain confidential and/or privileged
>> material. Any review, retransmission, dissemination or other use of, or
>> taking of any action in reliance upon, this information by persons or
>> entities other than the intended recipient is prohibited. If you received
>> this in error, please contact the sender and delete the material from any
>> computer. Thank you.
>>
>
>
>
> --
> La información transmitida es sólo para la persona o entidad a la cual está
> dirigida y puede contener material privilegiado y/o confidencial. Está
> prohibida cualquier revisión, retransmisión, difusión o cualquier otro uso
> de esta información, o la realización de cualquier acto en base a esta
> información por personas o entidades diferentes a las originalmente
> dirigidas. Si ha recibido esta información por error, por favor, póngase en
> contacto con el remitente y elimine el material de cualquier computadora.
> Muchas gracias.
>
> The information transmitted is intended only for the person or entity to
> which it is addressed and may contain confidential and/or privileged
> material. Any review, retransmission, dissemination or other use of, or
> taking of any action in reliance upon, this information by persons or
> entities other than the intended recipient is prohibited. If you received
> this in error, please contact the sender and delete the material from any
> computer. Thank you.
>



-- 
La información transmitida es sólo para la persona o entidad a la cual está
dirigida y puede contener material privilegiado y/o confidencial. Está
prohibida cualquier revisión, retransmisión, difusión o cualquier otro uso
de esta información, o la realización de cualquier acto en base a esta
información por personas o entidades diferentes a las originalmente
dirigidas. Si ha recibido esta información por error, por favor, póngase en
contacto con el remitente y elimine el material de cualquier computadora.
Muchas gracias.

The information transmitted is intended only for the person or entity to
which it is addressed and may contain confidential and/or privileged
material. Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by persons or
entities other than the intended recipient is prohibited. If you received
this in error, please contact the sender and delete the material from any
computer. Thank you.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/nice/attachments/20120817/fd832ba1/attachment-0001.html>
-------------- next part --------------
void cb_candidate_gathering_done (NiceAgent *agent,guint stream_id, gpointer user_data) {
  
  signal_data *dta = (signal_data *) user_data;
  

  dta->localCands = nice_agent_get_local_candidates (agent, stream_id, 1);

  gchar *frag, *pwd;
  nice_agent_get_local_credentials (agent, stream_id, &frag, &pwd);
  //mandarle al randezvous un paquete que tenga usr, pwd y el binario (capaz que conviene base64).
   
  char *cands =  writeCandsToChar(dta->localCands);

  if(0 > get_remote_sdp(frag, pwd, cands, myId, interestedId)) 
    exit_("ERROR: Intercambio de datos con el randevouz fallo.", dta);
  free(cands);
  //recibe el binario, usr y pwd desde el randezvous
  dta->remoteCands = readCandsChar(r_candidates);
  
  // tiago: print local candidates
  GSList *i;
  int n = 0;
  for (i = dta->remoteCands; i; i = i->next) {
    NiceCandidate *cand = (NiceCandidate *) i->data;
    printf("CANDIDADE NUMBER %d:\n",n);
    print_candidate_info(cand);
    n++;
  }
   
  g_assert(dta->remoteCands);
  g_assert(nice_agent_set_remote_credentials (agent, stream_id, r_user, r_pass));
  //need to change the credentials with the remote agent
  g_assert(dta->remoteCands);
  nice_agent_set_remote_candidates(agent, stream_id, 1, dta->remoteCands);


}

gboolean readFromChannel (GIOChannel *source, GIOCondition condition, gpointer data){
  
//  printf("------------------------readFromChannel-------------------------------\n");
  
  GError *error = NULL;
  gchar *buf = (gchar *)malloc(MAX_PACKAGE * sizeof(gchar));
  gsize bytes_read;
  
  signal_data *dta = (signal_data *) data;
  
  if (g_io_channel_read_chars(dta->channel, buf, MAX_PACKAGE, &bytes_read, &error) == G_IO_STATUS_ERROR) {
    printf("ERROR g_io_channel_read_chars: %s", error->message);
    free(buf);
    exit_("ERROR g_io_channel_read_chars", dta);
  }
  
  //get data from channel
  gint ret = nice_agent_send(dta->agent, dta->stream_id, NICE_COMPONENT_TYPE_RTP, bytes_read, buf);
  if (ret < 0 || ret != bytes_read){
    //ret si no es error es igual a la cantidad de bytes que se pudieron enviar
    
    free(buf);
    printf("ret= %i (si no es error es igual a la cantidad de bytes que se pudieron enviar)------------>>>>>>>>>>>>>>\n",ret);
    exit_("ERROR sending data", dta);
  }
  
  free(buf);
}

gboolean exitFromChannel (GIOChannel *source, GIOCondition condition, gpointer data){
  signal_data *dta = (signal_data *) data;
  exit_("exitFromChannel", dta);
}



void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer user_data){
  printf ("cb_component_state_changed\n");
  
	fd_set read_flags,write_flags; // the flag sets to be used
	struct timeval waitd;          // the max wait time for an event
	char buffer[MAX_PACKAGE + 1];             // input holding buffer
	int stat;                      // holds return value for select();

	int sock_ext = 0;
	
	signal_data *dta = (signal_data *) user_data;
	
	puts("cb_component_state_changed");
	char *NiceComponentStateString[] = {
		"NICE_COMPONENT_STATE_DISCONNECTED",
		"NICE_COMPONENT_STATE_GATHERING",
		"NICE_COMPONENT_STATE_CONNECTING",
		"NICE_COMPONENT_STATE_CONNECTED",
		"NICE_COMPONENT_STATE_READY",
		"NICE_COMPONENT_STATE_FAILED",
		"NICE_COMPONENT_STATE_LAST" };

	puts("CB_COMPONENT STATE CHANGED");
	printf("%d : %s\n", state, NiceComponentStateString[state]);

	switch(state)
	{
		case NICE_COMPONENT_STATE_READY:
		  
	  
		case NICE_COMPONENT_STATE_CONNECTED:
		  //aca es donde se mandan los datos
			sock_ext = connectToLib(dta);
			printf("sock_ext: %i\n",sock_ext);
			if (sock_ext==0)
			  exit(2);
			if (sock_ext > -1) {
			  GError *error = NULL;
			  dta->channel = g_io_channel_unix_new(sock_ext);
			  printf("dta->channel: %i\n", dta->channel);
			  //exit(2);
			  if (g_io_channel_set_encoding(dta->channel, NULL, &error) == G_IO_STATUS_ERROR) {
			    printf("ERROR g_io_channel_set_encoding: %s\n", error->message);
			    exit_("ERROR setting g_io_channel_set_encoding", dta);
			  }			  
			  g_io_add_watch(dta->channel, (GIOCondition) (G_IO_IN | G_IO_PRI), (GIOFunc)readFromChannel, dta);
			  g_io_add_watch(dta->channel, (GIOCondition) (G_IO_ERR | G_IO_HUP), (GIOFunc)exitFromChannel, dta);
			  printf("g_io_add_watch\n");
			  fflush(NULL);
			  
			} else {
			  exit_("Socket not open in ConnectToLib", dta);
			}
			break;
			
		case NICE_COMPONENT_STATE_FAILED: //fechar loop
			exit_("Nice component state failed.", dta);
			break;
			
		case NICE_COMPONENT_STATE_DISCONNECTED:
		  exit_("Estado de desconexion", dta);
	}
  return;
}

void cb_new_selected_pair (NiceAgent *agent, guint stream_id, guint component_id, gchar *lfoundation, gchar *rfoundation, gpointer user_data)
{
  printf ("cb_new_selected_pair\n");
}

void cb_nice_recv (NiceAgent * agent, guint stream_id, guint component_id, guint len, gchar * buf, gpointer user_data) {
  //aca es donde se reciben los datos
  printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>cb_nice_recv>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  
  
  signal_data *dta = (signal_data *) user_data;
  GError *error = NULL;
  gsize bytes_written;
  if (g_io_channel_write_chars(dta->channel, buf, len, &bytes_written, &error) == G_IO_STATUS_ERROR) {
    exit_("ERROR escriviendo en el canal", dta);
  }
  
  if (bytes_written != len) {
    exit_("ERROR escriviendo en el canal no escrivi todos los bytes", dta);
  }
  
}

  ////////////////////////////////
  //funciones que nice precisa fin
  ////////////////////////////////


void* establish_nice(void* arg){
  printf("void* establish_nice(void* arg){------------------------------------------------------------------------\n");
  
  signal_data data;
  data.agent = NULL;
  data.localCands = NULL;
  data.remoteCands = NULL;
  data.loop = NULL;
  data.channel = NULL;
  
  // lock on the mutex before changing the global variable no_threads
  g_mutex_lock(mutex_);
  no_threads++;
  //unlock the mutex
  g_mutex_unlock(mutex_);
  
  cant_datos_mandados = 0;
  strcpy(myId, ((ice_args *) arg)->my_id); 
  
  strcpy(interestedId, ((ice_args *) arg)->interested_in);
  
  free(arg);
  
  /////////////////////////////
  //conectarnos por nice inicio
  /////////////////////////////
  
  g_type_init ();
  g_thread_init (NULL);
// 
  data.loop = g_main_loop_new (NULL, FALSE);

  nice_debug_enable (TRUE);

  // Create a nice agent
  //Es reliable porque es el que implementa el TCP sobre UDP
  NiceAgent* agent = nice_agent_new_reliable (g_main_loop_get_context (data.loop), NICE_COMPATIBILITY_RFC5245);
  data.agent = agent;

  g_object_set (G_OBJECT (agent), "stun-server", STUN_ADDR, "stun-server-port", STUN_PORT, NULL);

  // Connect the signals
  g_signal_connect (G_OBJECT (agent), "candidate-gathering-done", G_CALLBACK (cb_candidate_gathering_done), &data);
  g_signal_connect (G_OBJECT (agent), "component-state-changed", G_CALLBACK (cb_component_state_changed), &data);
  g_signal_connect (G_OBJECT (agent), "new-selected-pair", G_CALLBACK (cb_new_selected_pair), &data);

  // Create a new stream with one component and start gathering candidates
  data.stream_id = nice_agent_add_stream (agent, 1);
  

  
  // Attach to the component to receive the data

  nice_agent_attach_recv (agent, data.stream_id, 1, g_main_loop_get_context (data.loop), cb_nice_recv, &data);
  nice_agent_gather_candidates (agent, data.stream_id);

  ///////////////////////////
  //conectarnos por nice fin
  ///////////////////////////
  
  //esto es el loop en el que queda corriendo, mientras atiende los eventos
  g_main_loop_run (data.loop);
  
  exit_("GOOD ENDING.", &data);
  
  return NULL;
  
}


More information about the nice mailing list