Client library rewrites.
[silc.git] / lib / silcclient / client_register.c
1 /*
2
3   client_register.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2006 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silc.h"
21 #include "silcclient.h"
22 #include "client_internal.h"
23
24 /************************** Types and definitions ***************************/
25
26
27 /************************ Static utility functions **************************/
28
29
30 /****************************** NEW_ID packet *******************************/
31
32 /* Received new ID packet from server during registering to SILC network */
33
34 SILC_FSM_STATE(silc_client_new_id)
35 {
36   SilcClientConnection conn = fsm_context;
37   SilcClient client = conn->client;
38   SilcPacket packet = state_context;
39   SilcID id;
40
41   if (conn->local_id)
42     goto out;
43
44   SILC_LOG_DEBUG(("New ID received from server"));
45
46   if (!silc_id_payload_parse_id(silc_buffer_data(&packet->buffer),
47                                 silc_buffer_len(&packet->buffer), &id))
48     goto out;
49
50   /* Create local client entry */
51   conn->local_entry = silc_client_add_client(client, conn,
52                                              (client->nickname ?
53                                               client->nickname :
54                                               client->username),
55                                              client->username,
56                                              client->realname,
57                                              &id.u.client_id, 0);
58   if (!conn->local_entry)
59     goto out;
60
61   /* Save the ID */
62   conn->local_id = &conn->local_entry->id;
63   conn->local_idp = silc_buffer_copy(&packet->buffer);
64
65   /* Save cache entry */
66   silc_idcache_find_by_id_one(conn->internal->client_cache, conn->local_id,
67                               &conn->internal->local_entry);
68
69   /* Save remote ID */
70   if (packet->src_id_len) {
71     conn->remote_idp = silc_id_payload_encode_data(packet->src_id,
72                                                    packet->src_id_len,
73                                                    packet->src_id_type);
74     if (!conn->remote_idp)
75       goto out;
76     silc_id_payload_parse_id(silc_buffer_data(conn->remote_idp),
77                              silc_buffer_len(conn->remote_idp),
78                              &conn->remote_id);
79   }
80
81   /* Signal connection that new ID was received so it can continue
82      with the registering. */
83   if (conn->internal->registering)
84     silc_fsm_continue_sync(&conn->internal->event_thread);
85
86  out:
87   /** Packet processed */
88   silc_packet_free(packet);
89   return SILC_FSM_FINISH;
90 }
91
92
93 /************************ Register to SILC network **************************/
94
95 /* Register to network */
96
97 SILC_FSM_STATE(silc_client_st_register)
98 {
99   SilcClientConnection conn = fsm_context;
100   SilcClient client = conn->client;
101
102   SILC_LOG_DEBUG(("Register to network"));
103
104   /* Send NEW_CLIENT packet to register to network */
105   if (!silc_packet_send_va(conn->stream, SILC_PACKET_NEW_CLIENT, 0,
106                            SILC_STR_UI_SHORT(strlen(client->username)),
107                            SILC_STR_DATA(client->username,
108                                          strlen(client->username)),
109                            SILC_STR_UI_SHORT(strlen(client->realname)),
110                            SILC_STR_DATA(client->realname,
111                                          strlen(client->realname)),
112                            SILC_STR_END)) {
113     /** Error sending packet */
114     silc_fsm_next(fsm, silc_client_st_register_error);
115     return SILC_FSM_CONTINUE;
116   }
117
118   /** Wait for new ID */
119   conn->internal->registering = TRUE;
120   silc_fsm_next_later(fsm, silc_client_st_register_complete, 15, 0);
121   return SILC_FSM_WAIT;
122 }
123
124 /* Wait for NEW_ID packet to arrive */
125
126 SILC_FSM_STATE(silc_client_st_register_complete)
127 {
128   SilcClientConnection conn = fsm_context;
129   SilcClient client = conn->client;
130
131   if (!conn->local_id) {
132     /* Timeout, ID not received */
133     conn->internal->registering = FALSE;
134     silc_fsm_next(fsm, silc_client_st_register_error);
135     return SILC_FSM_CONTINUE;
136   }
137
138   SILC_LOG_DEBUG(("Registered to network"));
139
140   /* Issue IDENTIFY command for itself to get resolved hostname
141      correctly from server. */
142   silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY, NULL, NULL,
143                            1, 5, silc_buffer_data(conn->local_idp),
144                            silc_buffer_len(conn->local_idp));
145
146   /* Send NICK command if the nickname was set by the application (and is
147      not same as the username).  Send this with little timeout. */
148   if (client->nickname &&
149       !silc_utf8_strcasecmp(client->nickname, client->username))
150     silc_client_command_send(client, conn, SILC_COMMAND_NICK, NULL, NULL,
151                              1, 1, client->nickname, strlen(client->nickname));
152
153   /* Issue INFO command to fetch the real server name and server
154      information and other stuff. */
155   silc_client_command_send(client, conn, SILC_COMMAND_INFO, NULL, NULL,
156                            1, 2, silc_buffer_data(conn->remote_idp),
157                            silc_buffer_len(conn->remote_idp));
158
159   /* Call connection callback.  We are now inside SILC network. */
160   conn->callback(client, conn, SILC_CLIENT_CONN_SUCCESS, 0, NULL,
161                  conn->context);
162
163   conn->internal->registering = FALSE;
164   return SILC_FSM_FINISH;
165 }
166
167 SILC_FSM_STATE(silc_client_st_register_error)
168 {
169   SilcClientConnection conn = fsm_context;
170   SilcClient client = conn->client;
171
172   /* XXX */
173   /* Close connection */
174
175   conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL, conn->context);
176
177   return SILC_FSM_FINISH;
178 }
179
180
181 /************************* Resume detached session **************************/
182
183 /* Resume detached session */
184
185 SILC_FSM_STATE(silc_client_st_resume)
186 {
187
188   return SILC_FSM_FINISH;
189 }
190
191 SILC_FSM_STATE(silc_client_st_resume_new_id)
192 {
193   SilcClientConnection conn = fsm_context;
194
195   return SILC_FSM_FINISH;
196 }
197
198 SILC_FSM_STATE(silc_client_st_resume_error)
199 {
200   /* XXX */
201   /* Close connection */
202
203   return SILC_FSM_FINISH;
204 }