Added support for SILC protocol 1.3 NEW_CLIENT packet.
[silc.git] / lib / silcclient / client_register.c
index c5f4cfc95dbe5a61ce4912ab631beb7e53d0c4e5..88726f5ea2f6961a4cb03ad63b065a2e089db9e4 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2006 Pekka Riikonen
+  Copyright (C) 2006 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -156,9 +156,15 @@ SILC_FSM_STATE(silc_client_st_register)
 {
   SilcClientConnection conn = fsm_context;
   SilcClient client = conn->client;
+  char *nick = NULL;
 
   SILC_LOG_DEBUG(("Register to network"));
 
+  /* From SILC protocol version 1.3, nickname is in NEW_CLIENT packet */
+  if (conn->internal->remote_version >= 13)
+    nick = (conn->internal->params.nickname ?
+           conn->internal->params.nickname : client->username);
+
   /* Send NEW_CLIENT packet to register to network */
   if (!silc_packet_send_va(conn->stream, SILC_PACKET_NEW_CLIENT, 0,
                           SILC_STR_UI_SHORT(strlen(client->username)),
@@ -167,6 +173,8 @@ SILC_FSM_STATE(silc_client_st_register)
                           SILC_STR_UI_SHORT(strlen(client->realname)),
                           SILC_STR_DATA(client->realname,
                                         strlen(client->realname)),
+                          SILC_STR_UI_SHORT(nick ? strlen(nick) : 0),
+                          SILC_STR_DATA(nick, nick ? strlen(nick) : 0),
                           SILC_STR_END)) {
     /** Error sending packet */
     silc_fsm_next(fsm, silc_client_st_register_error);
@@ -221,9 +229,9 @@ SILC_FSM_STATE(silc_client_st_register_complete)
                           1, 5, silc_buffer_data(conn->internal->local_idp),
                           silc_buffer_len(conn->internal->local_idp));
 
-  /* Call NICK command if the nickname was set by the application (and is
-     not same as the username). */
-  if (conn->internal->params.nickname &&
+  /* With SILC protocol version 1.2 call NICK command if the nickname was
+     set by the application. */
+  if (conn->internal->params.nickname && conn->internal->remote_version < 13 &&
       !silc_utf8_strcasecmp(conn->internal->params.nickname, client->username))
     silc_client_command_call(client, conn, NULL,
                             "NICK", conn->internal->params.nickname, NULL);
@@ -251,22 +259,16 @@ SILC_FSM_STATE(silc_client_st_register_complete)
 SILC_FSM_STATE(silc_client_st_register_error)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
 
   SILC_LOG_DEBUG(("Error registering to network"));
 
   /* Signal to close connection */
+  conn->internal->status = SILC_CLIENT_CONN_ERROR;
   if (!conn->internal->disconnected) {
     conn->internal->disconnected = TRUE;
-    SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+    SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
   }
 
-  /* Call connect callback */
-  if (conn->internal->callback_called)
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
-                  conn->callback_context);
-  conn->internal->callback_called = TRUE;
-
   silc_schedule_task_del_by_all(conn->internal->schedule, 0,
                                silc_client_connect_timeout, conn);
 
@@ -382,6 +384,9 @@ SILC_FSM_STATE(silc_client_st_resume_resolve_channels)
     return SILC_FSM_CONTINUE;
   }
 
+  /** Wait for channels */
+  silc_fsm_next(fsm, silc_client_st_resume_resolve_cmodes);
+
   /* Change our nickname */
   silc_client_change_nickname(client, conn, conn->local_entry,
                              resume->nickname, NULL, NULL, 0);
@@ -393,6 +398,9 @@ SILC_FSM_STATE(silc_client_st_resume_resolve_channels)
                           1, 1, silc_buffer_data(conn->internal->local_idp),
                           silc_buffer_len(conn->internal->local_idp));
 
+  if (!resume->channel_count)
+    return SILC_FSM_YIELD;
+
   /* Send IDENTIFY command for all channels we know about.  These are the
      channels we've joined to according our detachment data. */
   for (i = 0; i < resume->channel_count; i++) {
@@ -447,8 +455,6 @@ SILC_FSM_STATE(silc_client_st_resume_resolve_channels)
   silc_free(res_argv_lens);
   silc_free(res_argv_types);
 
-  /** Wait for channels */
-  silc_fsm_next(fsm, silc_client_st_resume_resolve_cmodes);
   return SILC_FSM_WAIT;
 }
 
@@ -476,7 +482,7 @@ SILC_FSM_STATE(silc_client_st_resume_resolve_cmodes)
   silc_fsm_next(fsm, silc_client_st_resume_completed);
 
   if (!silc_idcache_get_all(conn->internal->channel_cache, &channels))
-    return SILC_FSM_CONTINUE;
+    return SILC_FSM_YIELD;
 
   /* Resolve channels' mode, users and topic */
   resume->channel_count = silc_list_count(channels) * 3;
@@ -548,6 +554,11 @@ SILC_FSM_STATE(silc_client_st_resume_completed)
   conn->callback(client, conn, SILC_CLIENT_CONN_SUCCESS_RESUME, 0, NULL,
                 conn->callback_context);
 
+  /* Call UMODE command reply. */
+  if (conn->local_entry->mode)
+    silc_client_resume_command_callback(client, conn, SILC_COMMAND_UMODE,
+                                       conn->local_entry->mode);
+
   /* Call NICK command reply. */
   silc_client_resume_command_callback(client, conn, SILC_COMMAND_NICK,
                                      conn->local_entry,
@@ -562,8 +573,8 @@ SILC_FSM_STATE(silc_client_st_resume_completed)
     const char *cipher, *hmac;
 
     channel = entry->context;
-    cipher = (channel->internal.channel_key ?
-             silc_cipher_get_name(channel->internal.channel_key) : NULL);
+    cipher = (channel->internal.send_key ?
+             silc_cipher_get_name(channel->internal.send_key) : NULL);
     hmac = (channel->internal.hmac ?
            silc_hmac_get_name(channel->internal.hmac) : NULL);
     silc_hash_table_list(channel->user_list, &htl);
@@ -590,7 +601,6 @@ SILC_FSM_STATE(silc_client_st_resume_completed)
 SILC_FSM_STATE(silc_client_st_resume_error)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
   SilcClientResumeSession resume = state_context;
 
   if (conn->internal->disconnected) {
@@ -604,17 +614,12 @@ SILC_FSM_STATE(silc_client_st_resume_error)
   SILC_LOG_DEBUG(("Error resuming to network"));
 
   /* Signal to close connection */
+  conn->internal->status = SILC_CLIENT_CONN_ERROR;
   if (!conn->internal->disconnected) {
     conn->internal->disconnected = TRUE;
-    SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+    SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
   }
 
-  /* Call connect callback */
-  if (conn->internal->callback_called)
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
-                  conn->callback_context);
-  conn->internal->callback_called = TRUE;
-
   silc_schedule_task_del_by_all(conn->internal->schedule, 0,
                                silc_client_connect_timeout, conn);