SILC FSM API changes.
threads that need execution time also.
-When to use FSM semaphore signalling?
+When to use FSM event signalling?
- FSM semaphore signalling should be used only when multiple threads
+ FSM event signalling should be used only when multiple threads
(FSM threads) may be waiting for something to happen. If only one thread
is waiting for something it should merely return SILC_FSM_WAIT and when
that something happens it should use silc_fsm_continue or
silc_fsm_continue_sync to continue in the waiting thread. OTOH, if
- multiple threads are waiting SILC_FSM_SEMA_POST is the only way to
+ multiple threads are waiting SILC_FSM_EVENT_SIGNAL is the only way to
deliver the signal. Always remember that posting is signal is not
donbe synchronously (it won't be delivered immediately).
OTOH, if there is only one thread waiting for somtehing to happen but
there can be multiple threads signalling that something has happened
- only way to do this is to use semaphore signalling.
+ only way to do this is to use event signalling.
- Semaphore signals should be pre-allocated SilcFSMSemaStruct structures
+ Event signals should be pre-allocated SilcFSMEventStruct structures
and for signalling use they are always initialized as:
- silc_fsm_sema_init(&sema, fsm, 0);
+ silc_fsm_event_init(&event, fsm);
- The call cannot fail. Semaphores need not be uninitialized and the same
+ The call cannot fail. Events need not be uninitialized and the same
context may be reused.
Finishing threads when closing connection
/* Signal client that we have finished */
silc_atomic_sub_int16(&client->internal->conns, 1);
client->internal->connection_closed = TRUE;
- SILC_FSM_SEMA_POST(&client->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
silc_fsm_free(fsm);
}
/* Signal to close connection */
if (!conn->internal->disconnected) {
conn->internal->disconnected = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
}
}
/* Signal to close connection */
if (!conn->internal->disconnected) {
conn->internal->disconnected = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
}
}
connfsm = &conn->internal->fsm;
silc_fsm_init(connfsm, conn, silc_client_connection_destructor,
fsm, conn->internal->schedule);
- silc_fsm_sema_init(&conn->internal->wait_event, connfsm, 0);
+ silc_fsm_event_init(&conn->internal->wait_event, connfsm);
silc_fsm_start_sync(connfsm, silc_client_connection_st_run);
/* Schedule any events set in initialization */
if (conn->internal->connect)
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
if (conn->internal->key_exchange)
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
/* Wait until this thread is terminated from the machine destructor */
- return SILC_FSM_WAIT;
+ SILC_FSM_WAIT;
}
/* Connection machine main state. This handles various connection related
SilcFSMThread thread;
/* Wait for events */
- SILC_FSM_SEMA_WAIT(&conn->internal->wait_event);
+ SILC_FSM_EVENT_WAIT(&conn->internal->wait_event);
/* Process events */
thread = &conn->internal->event_thread;
silc_fsm_thread_init(thread, &conn->internal->fsm, conn,
NULL, NULL, FALSE);
silc_fsm_start_sync(thread, silc_client_st_connect);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (conn->internal->key_exchange) {
silc_fsm_thread_init(thread, &conn->internal->fsm, conn,
NULL, NULL, FALSE);
silc_fsm_start_sync(thread, silc_client_st_connect_set_stream);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (conn->internal->rekeying) {
silc_fsm_thread_init(thread, &conn->internal->fsm, conn,
NULL, NULL, FALSE);
silc_fsm_start_sync(thread, silc_client_st_rekey);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (conn->internal->disconnected) {
/** Event: disconnected */
SILC_LOG_DEBUG(("Event: disconnected"));
silc_fsm_next(fsm, silc_client_connection_st_close);
- return SILC_FSM_YIELD;
+ SILC_FSM_YIELD;
}
/* NOT REACHED */
SILC_ASSERT(FALSE);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Packet processor thread. Each incoming packet is processed in FSM
/* Signal to start rekey */
conn->internal->rekey_responder = TRUE;
conn->internal->rekeying = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
break;
default:
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
break;
}
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Disconnection event to close remote connection. We close the connection
}
/* Give threads time to finish */
- return SILC_FSM_YIELD;
+ SILC_FSM_YIELD;
}
/* Abort ongoing event */
if (silc_fsm_is_started(&conn->internal->event_thread)) {
SILC_LOG_DEBUG(("Finish event thread"));
silc_fsm_continue_sync(&conn->internal->event_thread);
- return SILC_FSM_YIELD;
+ SILC_FSM_YIELD;
}
SILC_LOG_DEBUG(("Closing remote connection"));
SILC_LOG_DEBUG(("Finishing connection machine"));
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Received error packet from server. Send it to application. */
silc_free(msg);
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Received disconnect packet from server. We close the connection and
if (silc_buffer_len(&packet->buffer) < 1) {
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
status = (SilcStatus)packet->buffer.data[0];
/* Signal to close connection */
if (!conn->internal->disconnected) {
conn->internal->disconnected = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
}
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/*************************** Main client machine ****************************/
SilcClient client = fsm_context;
/* Wait for events */
- SILC_FSM_SEMA_WAIT(&client->internal->wait_event);
+ SILC_FSM_EVENT_WAIT(&client->internal->wait_event);
/* Process events */
SILC_LOG_DEBUG(("We are up, call running callback"));
client->internal->run_callback = FALSE;
client->internal->running(client, client->internal->running_context);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (client->internal->connection_closed) {
client->internal->connection_closed = FALSE;
if (silc_atomic_get_int16(&client->internal->conns) == 0 &&
client->internal->stop)
- SILC_FSM_SEMA_POST(&client->internal->wait_event);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
+ SILC_FSM_CONTINUE;
}
if (client->internal->stop) {
SILC_LOG_DEBUG(("Event: stop"));
if (silc_atomic_get_int16(&client->internal->conns) == 0)
silc_fsm_next(fsm, silc_client_st_stop);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* NOT REACHED */
SILC_ASSERT(FALSE);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Stop event. Stops the client library. */
if (client->internal->running)
client->internal->running(client, client->internal->running_context);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/******************************* Private API ********************************/
/* Signal to close connection */
if (!conn->internal->disconnected) {
conn->internal->disconnected = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
}
}
client->internal->running = running;
client->internal->running_context = context;
silc_fsm_init(&client->internal->fsm, client, NULL, NULL, client->schedule);
- silc_fsm_sema_init(&client->internal->wait_event, &client->internal->fsm, 0);
+ silc_fsm_event_init(&client->internal->wait_event, &client->internal->fsm);
silc_fsm_start_sync(&client->internal->fsm, silc_client_st_run);
/* Signal the application when we are running */
client->internal->run_callback = TRUE;
- SILC_FSM_SEMA_POST(&client->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
return TRUE;
}
/* Signal to stop */
client->internal->stop = TRUE;
- SILC_FSM_SEMA_POST(&client->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
}
if (silc_unlikely(packet->dst_id_type != SILC_ID_CHANNEL)) {
/** Invalid packet */
silc_fsm_next(fsm, silc_client_channel_message_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (silc_unlikely(!silc_id_str2id(packet->src_id,
&remote_id, sizeof(remote_id)))) {
/** Invalid source ID */
silc_fsm_next(fsm, silc_client_channel_message_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Get sender client entry */
sizeof(channel_id)))) {
/** Invalid destination ID */
silc_fsm_next(fsm, silc_client_channel_message_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Find the channel */
if (silc_unlikely(!channel)) {
/** Unknown channel */
silc_fsm_next(fsm, silc_client_channel_message_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Check that user is on channel */
SILC_LOG_WARNING(("Message from user not on channel, client or "
"server bug"));
silc_fsm_next(fsm, silc_client_channel_message_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* If there is no channel private key then just decrypt the message
silc_client_unref_channel(client, conn, channel);
if (payload)
silc_message_payload_free(payload);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Channel message error. */
{
SilcPacket packet = state_context;
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/******************************* Channel Key ********************************/
silc_client_save_channel_key(client, conn, &packet->buffer, NULL);
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/**************************** Channel Private Key ***************************/
conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
conn->callback_context);
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Connect (UDP) */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Create packet stream */
conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
conn->callback_context);
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
silc_packet_set_context(conn->stream, conn);
/** Start key exchange */
silc_fsm_next(fsm, silc_client_st_connect_key_exchange);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Starts key exchange protocol with remote host */
conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_KE, 0, NULL,
conn->callback_context);
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Set SKE callbacks */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Create new UDP stream */
conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
conn->callback_context);
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Set the new stream to packet stream */
old = silc_packet_stream_get_stream(conn->stream);
- silc_packet_stream_set_stream(conn->stream, stream,
- conn->internal->schedule);
+ silc_packet_stream_set_stream(conn->stream, stream);
silc_packet_stream_set_iv_included(conn->stream);
silc_packet_set_sid(conn->stream, 0);
/** Start authentication */
silc_fsm_next(fsm, silc_client_st_connect_auth);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Get authentication method to be used in authentication protocol */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
silc_fsm_next(fsm, silc_client_st_connect_auth_start);
conn->internal->params.auth = conn->private_key;
/* We have authentication data */
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Start connection authentication with remote host */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Allocate connection authentication protocol */
conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_AUTH, 0, NULL,
conn->callback_context);
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/** Start connection authentication */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_connect_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
SILC_LOG_DEBUG(("Connection established"));
silc_fsm_next(fsm, silc_client_st_register);
}
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
silc_schedule_task_del_by_all(conn->internal->schedule, 0,
conn->callback(client, conn, SILC_CLIENT_CONN_SUCCESS, 0, NULL,
conn->callback_context);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Error during connecting */
/* Signal to close connection */
if (!conn->internal->disconnected) {
conn->internal->disconnected = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
}
silc_schedule_task_del_by_all(conn->internal->schedule, 0,
silc_client_connect_timeout, conn);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/****************************** Connect rekey *******************************/
/* Signal to start rekey */
conn->internal->rekey_responder = FALSE;
conn->internal->rekeying = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
/* Reinstall rekey timer */
silc_schedule_task_add_timeout(conn->internal->schedule,
SILC_LOG_DEBUG(("Rekey"));
if (conn->internal->disconnected)
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
/* Allocate SKE */
conn->internal->ske =
conn->internal->params.repository,
conn->public_key, conn->private_key, fsm);
if (!conn->internal->ske)
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
/* Set SKE callbacks */
silc_ske_set_callbacks(conn->internal->ske, NULL,
}
/* Format the nickname */
- silc_client_nickname_format(client, conn, client_entry);
+ silc_client_nickname_format(client, conn, client_entry, FALSE);
silc_mutex_lock(conn->internal->lock);
return;
/* Format nickname */
- silc_client_nickname_format(client, conn, client_entry);
+ silc_client_nickname_format(client, conn, client_entry,
+ client_entry == conn->local_entry);
/* Update cache entry */
silc_mutex_lock(conn->internal->lock);
memset(client_entry->nickname, 0, sizeof(client_entry->nickname));
memcpy(client_entry->nickname, new_nick, strlen(new_nick));
client_entry->nickname_normalized = tmp;
- silc_client_nickname_format(client, conn, client_entry);
+ silc_client_nickname_format(client, conn, client_entry,
+ client_entry == conn->local_entry);
/* For my client entry, update ID and set new ID to packet stream */
if (client_entry == conn->local_entry) {
/* Formats the nickname of the client specified by the `client_entry'.
If the format is specified by the application this will format the
nickname and replace the old nickname in the client entry. If the
- format string is not specified then this function has no effect. */
+ format string is not specified then this function has no effect.
+ Returns the client entry that was formatted. */
-void silc_client_nickname_format(SilcClient client,
- SilcClientConnection conn,
- SilcClientEntry client_entry)
+SilcClientEntry silc_client_nickname_format(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry,
+ SilcBool priority)
{
char *cp;
char newnick[128 + 1];
SilcDList clients;
SilcClientEntry entry, unformatted = NULL;
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Format nickname"));
if (!client->internal->params->nickname_format[0])
- return;
-
+ return client_entry;
if (!client_entry->nickname[0])
- return;
+ return NULL;
/* Get all clients with same nickname. Do not perform the formatting
if there aren't any clients with same nickname unless the application
is forcing us to do so. */
clients = silc_client_get_clients_local(client, conn,
client_entry->nickname, NULL);
- if (!clients && !client->internal->params->nickname_force_format)
- return;
+ if (!clients)
+ return NULL;
+ if (silc_dlist_count(clients) == 1 &&
+ !client->internal->params->nickname_force_format) {
+ silc_client_list_free(client, conn, clients);
+ return client_entry;
+ }
- if (clients) {
- len = 0;
- freebase = TRUE;
- while ((entry = silc_dlist_get(clients))) {
- if (entry->internal.valid && entry != client_entry)
- len++;
- if (entry->internal.valid && entry != client_entry &&
- silc_utf8_strcasecmp(entry->nickname, client_entry->nickname)) {
- freebase = FALSE;
- unformatted = entry;
- }
- }
- if (!len || freebase) {
- silc_client_list_free(client, conn, clients);
- return;
+ len = 0;
+ freebase = TRUE;
+ while ((entry = silc_dlist_get(clients))) {
+ if (entry->internal.valid && entry != client_entry)
+ len++;
+ if (entry->internal.valid && entry != client_entry &&
+ silc_utf8_strcasecmp(entry->nickname, client_entry->nickname)) {
+ freebase = FALSE;
+ unformatted = entry;
+ break;
}
}
+ if (!len || freebase) {
+ silc_client_list_free(client, conn, clients);
+ return client_entry;
+ }
- /* If we are changing nickname of our local entry we'll enforce
- that we will always get the unformatted nickname. Give our
- format number to the one that is not formatted now. */
- if (unformatted && client_entry == conn->local_entry)
+ /* If priority formatting, this client always gets unformatted nickname. */
+ if (unformatted && priority)
client_entry = unformatted;
memset(newnick, 0, sizeof(newnick));
char tmp[6];
int num, max = 1;
- if (clients && silc_dlist_count(clients) == 1)
+ if (silc_dlist_count(clients) == 1)
break;
- if (clients) {
- silc_dlist_start(clients);
- while ((entry = silc_dlist_get(clients))) {
- if (!silc_utf8_strncasecmp(entry->nickname, newnick, off))
- continue;
- if (strlen(entry->nickname) <= off)
- continue;
- num = atoi(&entry->nickname[off]);
- if (num > max)
- max = num;
- }
+ silc_dlist_start(clients);
+ while ((entry = silc_dlist_get(clients))) {
+ if (!silc_utf8_strncasecmp(entry->nickname, newnick, off))
+ continue;
+ if (strlen(entry->nickname) <= off)
+ continue;
+ num = atoi(&entry->nickname[off]);
+ if (num > max)
+ max = num;
}
memset(tmp, 0, sizeof(tmp));
newnick[off] = 0;
memcpy(client_entry->nickname, newnick, strlen(newnick));
silc_client_list_free(client, conn, clients);
+
+ return client_entry;
+}
+
+/* Parses nickname according to nickname format string */
+
+SilcBool silc_client_nickname_parse(SilcClient client,
+ SilcClientConnection conn,
+ char *nickname,
+ char **ret_nick)
+{
+ char *cp, s = 0, e = 0, *nick;
+ SilcBool n = FALSE;
+ int len;
+
+ if (!client->internal->params->nickname_format[0])
+ return TRUE;
+
+ if (!nickname || !nickname[0])
+ return FALSE;
+
+ cp = client->internal->params->nickname_format;
+ while (cp && *cp) {
+ if (*cp == '%') {
+ cp++;
+ continue;
+ }
+
+ switch(*cp) {
+ case 'n':
+ n = TRUE;
+ break;
+
+ case 'h':
+ case 'H':
+ case 's':
+ case 'S':
+ case 'a':
+ break;
+
+ default:
+ /* Get separator character */
+ if (n)
+ e = *cp;
+ else
+ s = *cp;
+ break;
+ }
+
+ cp++;
+ }
+ if (!n)
+ return FALSE;
+
+ /* Parse the nickname */
+ nick = nickname;
+ len = strlen(nick);
+ if (s)
+ if (strchr(nickname, s))
+ nick = strchr(nickname, s) + 1;
+ if (e)
+ if (strchr(nick, e))
+ len = strchr(nick, e) - nick;
+ if (!len)
+ return FALSE;
+
+ *ret_nick = silc_memdup(nick, len);
+ if (!(*ret_nick))
+ return FALSE;
+
+ SILC_LOG_DEBUG(("Parsed nickname: %s", *ret_nick));
+
+ return TRUE;
}
/************************ Channel Searching Locally *************************/
SilcClientConnection conn,
SilcChannelEntry channel,
SilcChannelID *new_id);
-void silc_client_nickname_format(SilcClient client,
- SilcClientConnection conn,
- SilcClientEntry client_entry);
+SilcBool silc_client_nickname_parse(SilcClient client,
+ SilcClientConnection conn,
+ char *nickname,
+ char **ret_nick);
#endif /* CLIENT_ENTRY_H */
/* Internal context for the client->internal pointer in the SilcClient. */
struct SilcClientInternalStruct {
SilcFSMStruct fsm; /* Client's FSM */
- SilcFSMSemaStruct wait_event; /* Event signaller */
+ SilcFSMEventStruct wait_event; /* Event signaller */
SilcClientOperations *ops; /* Client operations */
SilcClientParams *params; /* Client parameters */
SilcPacketEngine packet_engine; /* Packet engine */
SilcClientConnectionParams params; /* Connection parameters */
SilcFSMStruct fsm; /* Connection FSM */
SilcFSMThreadStruct event_thread; /* FSM thread for events */
- SilcFSMSemaStruct wait_event; /* Event signaller */
+ SilcFSMEventStruct wait_event; /* Event signaller */
SilcSchedule schedule; /* Connection's scheduler */
SilcMutex lock; /* Connection lock */
SilcSKE ske; /* Key exchange protocol */
if (packet->src_id_type != SILC_ID_CLIENT) {
/** Invalid packet */
silc_fsm_next(fsm, silc_client_key_agreement_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
&remote_id, sizeof(remote_id))) {
/** Invalid source ID */
silc_fsm_next(fsm, silc_client_key_agreement_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Check whether we know this client already */
/** Malformed Payload */
SILC_LOG_DEBUG(("Malformed key agreement payload"));
silc_fsm_next(fsm, silc_client_key_agreement_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* If remote did not provide connection endpoint, we will assume that we
silc_key_agreement_payload_free(payload);
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Key agreement packet processing error */
{
SilcPacket packet = state_context;
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
if (!payload) {
SILC_LOG_DEBUG(("Malformed notify payload"));
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
if (!silc_notify_get_args(payload)) {
SILC_LOG_DEBUG(("Malformed notify %d", silc_notify_get_type(payload)));
silc_notify_payload_free(payload);
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
notify = silc_calloc(1, sizeof(*notify));
if (!notify) {
silc_notify_payload_free(payload);
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Save notify payload to packet context during processing */
silc_notify_payload_free(payload);
silc_packet_free(packet);
silc_free(notify);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
break;
}
- return SILC_FSM_YIELD;
+ SILC_FSM_YIELD;
}
/* Notify processed, finish the packet processing thread */
silc_notify_payload_free(payload);
silc_packet_free(packet);
silc_free(notify);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************** NONE ************************************/
/** Notify processed */
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* INVITE ***********************************/
/** Notify processed */
silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** JOIN ************************************/
}
if (client_entry != conn->local_entry)
- silc_client_nickname_format(client, conn, client_entry);
+ silc_client_nickname_format(client, conn, client_entry, FALSE);
/* Join the client to channel */
if (!silc_client_add_to_channel(client, conn, channel, client_entry, 0))
/** Notify processed */
silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** LEAVE ***********************************/
/** Notify processed */
silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* SIGNOFF **********************************/
out:
/** Notify processed */
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** TOPIC_SET *********************************/
/** Notify processed */
silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/****************************** NICK_CHANGE *********************************/
/** Notify processed */
silc_client_unref_client(client, conn, client_entry);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/****************************** CMODE_CHANGE ********************************/
/** Notify processed */
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/***************************** CUMODE_CHANGE ********************************/
/** Notify processed */
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* MOTD *************************************/
out:
/** Notify processed */
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/**************************** CHANNEL CHANGE ********************************/
/** Notify processed */
silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** KICKED ************************************/
/** Notify processed */
silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** KILLED ************************************/
/** Notify processed */
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/**************************** SERVER SIGNOFF ********************************/
/** Notify processed */
silc_client_list_free(client, conn, clients);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** ERROR *************************************/
out:
/** Notify processed */
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** WATCH *************************************/
if (tmp) {
char *tmp_nick = NULL;
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(client_entry->nickname,
- &tmp_nick);
- else
- tmp_nick = strdup(tmp);
+ silc_client_nickname_parse(client, conn, client_entry->nickname,
+ &tmp_nick);
/* If same nick, the client was new to us and has become "present"
to network. Send NULL as nick to application. */
/** Notify processed */
silc_client_unref_client(client, conn, client_entry);
silc_fsm_next(fsm, silc_client_notify_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (silc_unlikely(packet->src_id_type != SILC_ID_CLIENT)) {
/** Invalid packet */
silc_fsm_next(fsm, silc_client_private_message_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (silc_unlikely(!silc_id_str2id(packet->src_id, packet->src_id_len,
sizeof(remote_id)))) {
/** Invalid source ID */
silc_fsm_next(fsm, silc_client_private_message_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Check whether we know this client already */
silc_client_unref_client(client, conn, remote_client);
if (payload)
silc_message_payload_free(payload);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Private message error. */
{
SilcPacket packet = state_context;
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
#if 0 /* XXX we need to rethink this */
if (packet->src_id_type != SILC_ID_CLIENT) {
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
&remote_id, sizeof(remote_id))) {
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Always resolve the remote client. The actual packet is processed
out:
/** Packet processed */
silc_packet_free(packet);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
SILC_STR_END)) {
/** Error sending packet */
silc_fsm_next(fsm, silc_client_st_register_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/** Wait for new ID */
conn->internal->registering = TRUE;
silc_fsm_next_later(fsm, silc_client_st_register_complete,
conn->internal->retry_timer, 0);
- return SILC_FSM_WAIT;
+ SILC_FSM_WAIT;
}
/* Wait for NEW_ID packet to arrive */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_register_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (!conn->local_id) {
conn->internal->retry_count = 0;
conn->internal->retry_timer = SILC_CLIENT_RETRY_MIN;
silc_fsm_next(fsm, silc_client_st_register_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/** Resend registering packet */
SILC_CLIENT_RETRY_MUL) +
(silc_rng_get_rn16(client->rng) %
SILC_CLIENT_RETRY_RAND));
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
SILC_LOG_DEBUG(("Registered to network"));
silc_schedule_task_del_by_all(conn->internal->schedule, 0,
silc_client_connect_timeout, conn);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Error registering to network */
/* Signal to close connection */
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 */
silc_schedule_task_del_by_all(conn->internal->schedule, 0,
silc_client_connect_timeout, conn);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/************************* Resume detached session **************************/
if (!resume) {
/** Out of memory */
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
silc_fsm_set_state_context(fsm, resume);
/** Malformed detach data */
SILC_LOG_DEBUG(("Malformed detachment data"));
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (!silc_id_str2id(id, id_len, SILC_ID_CLIENT, &client_id,
/** Malformed ID */
SILC_LOG_DEBUG(("Malformed ID"));
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Generate authentication data that server will verify */
if (!auth) {
/** Out of memory */
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Send RESUME_CLIENT packet to resume to network */
/** Error sending packet */
SILC_LOG_DEBUG(("Error sending packet"));
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/** Wait for new ID */
conn->internal->registering = TRUE;
silc_fsm_next_later(fsm, silc_client_st_resume_resolve_channels, 15, 0);
- return SILC_FSM_WAIT;
+ SILC_FSM_WAIT;
}
/* Resolve the old session information, user mode and joined channels. */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (!conn->local_id) {
/** Timeout, ID not received */
conn->internal->registering = FALSE;
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ 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);
1, 1, silc_buffer_data(conn->internal->local_idp),
silc_buffer_len(conn->internal->local_idp));
+ if (!resume->channel_count)
+ 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++) {
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;
+ SILC_FSM_WAIT;
}
/* Resolve joined channel modes, users and topics. */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
SILC_LOG_DEBUG(("Resolving channel details"));
silc_fsm_next(fsm, silc_client_st_resume_completed);
if (!silc_idcache_get_all(conn->internal->channel_cache, &channels))
- return SILC_FSM_CONTINUE;
+ SILC_FSM_YIELD;
/* Resolve channels' mode, users and topic */
resume->channel_count = silc_list_count(channels) * 3;
silc_buffer_free(idp);
}
- return SILC_FSM_WAIT;
+ SILC_FSM_WAIT;
}
/* Resuming completed */
if (conn->internal->disconnected) {
/** Disconnected */
silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
if (resume->channel_count > 0) {
resume->channel_count--;
if (resume->channel_count)
- return SILC_FSM_WAIT;
+ SILC_FSM_WAIT;
}
SILC_LOG_DEBUG(("Resuming 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,
silc_free(resume->nickname);
silc_free(resume);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Error resuming to network */
silc_free(resume->nickname);
silc_free(resume);
}
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
SILC_LOG_DEBUG(("Error resuming to network"));
/* Signal to close connection */
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 */
silc_free(resume);
}
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Generates the session detachment data. This data can be used later
SILC_FSM_STATE(silc_client_command_continue_error)
{
/* Destructor will free all resources */
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Command reply callback to continue with the execution of a command.
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
for (i = 1; i < cmd->argc; i++) {
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/******************************** WHOWAS ************************************/
"Usage: /WHOWAS <nickname>[@<server>] [<count>]");
COMMAND_ERROR((cmd->argc < 2 ? SILC_STATUS_ERR_NOT_ENOUGH_PARAMS :
SILC_STATUS_ERR_TOO_MANY_PARAMS));
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
if (cmd->argc == 2) {
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** IDENTIFY **********************************/
int c;
if (cmd->argc < 2 || cmd->argc > 3)
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
if (cmd->argc == 2) {
silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL,
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** NICK ************************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************** LIST ************************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** TOPIC ***********************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************* INVITE ***********************************/
/* Parse the typed nickname. */
if (cmd->argc == 3) {
if (cmd->argv[2][0] != '+' && cmd->argv[2][0] != '-') {
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[2], &nickname);
- else
- nickname = strdup(cmd->argv[2]);
+ silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname);
/* Find client entry */
clients = silc_client_get_clients_local(client, conn, nickname,
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
silc_free(nickname);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************** QUIT ************************************/
/* Signal to close connection */
if (!conn->internal->disconnected) {
conn->internal->disconnected = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
}
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Command QUIT. Closes connection with current server. */
/* We close the connection with a little timeout */
silc_fsm_next_later(fsm, silc_client_command_quit_final, 2, 0);
- return SILC_FSM_WAIT;
+ SILC_FSM_WAIT;
}
/********************************** KILL ************************************/
SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /KILL <nickname> [<comment>] [-pubkey]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[1], &nickname);
- else
- nickname = strdup(cmd->argv[1]);
- if (!nickname)
- return SILC_FSM_FINISH;
+ if (!silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname))
+ SILC_FSM_FINISH;
/* Get the target client */
clients = silc_client_get_clients_local(client, conn, nickname,
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** INFO ************************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** STATS ***********************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** PING ************************************/
if (cmd->argc < 2) {
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Send the command */
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** JOIN ************************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************** MOTD ************************************/
"Usage: /MOTD [<server>]");
COMMAND_ERROR((cmd->argc < 1 ? SILC_STATUS_ERR_NOT_ENOUGH_PARAMS :
SILC_STATUS_ERR_TOO_MANY_PARAMS));
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Send the command */
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** UMODE ***********************************/
SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /UMODE +|-<modes>");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
mode = conn->local_entry->mode;
break;
default:
COMMAND_ERROR(SILC_STATUS_ERR_UNKNOWN_MODE);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
break;
}
}
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** CMODE ***********************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************* CUMODE ***********************************/
}
/* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[3], &nickname);
- else
- nickname = strdup(cmd->argv[3]);
+ silc_client_nickname_parse(client, conn, cmd->argv[3], &nickname);
/* Find client entry */
clients = silc_client_get_clients_local(client, conn, nickname,
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
silc_client_list_free(client, conn, clients);
silc_free(nickname);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************** KICK ************************************/
}
/* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[2], &nickname);
- else
- nickname = strdup(cmd->argv[2]);
+ silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname);
/* Get the target client */
clients = silc_client_get_clients_local(client, conn, nickname,
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
silc_free(nickname);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/***************************** OPER & SILCOPER ******************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* OPER command. Used to obtain server operator privileges. */
SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /OPER <username> [-pubkey]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Get passphrase */
if (cmd->argc < 3) {
oper = silc_calloc(1, sizeof(*oper));
if (!oper)
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
cmd->context = oper;
SILC_FSM_CALL(conn->client->internal->
ops->ask_passphrase(conn->client, conn,
}
silc_fsm_next(fsm, silc_client_command_oper_send);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* SILCOPER command. Used to obtain router operator privileges. */
SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /SILCOPER <username> [-pubkey]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Get passphrase */
if (cmd->argc < 3) {
oper = silc_calloc(1, sizeof(*oper));
if (!oper)
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
cmd->context = oper;
SILC_FSM_CALL(conn->client->internal->
ops->ask_passphrase(conn->client, conn,
}
silc_fsm_next(fsm, silc_client_command_oper_send);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/*********************************** BAN ************************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************* DETACH ***********************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** WATCH ***********************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************** LEAVE ***********************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************** USERS ***********************************/
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
out:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/********************************* GETKEY ***********************************/
client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /GETKEY <nickname or server name>");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[1], &nickname);
- else
- nickname = strdup(cmd->argv[1]);
- if (!nickname) {
+ if (!silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname)) {
COMMAND_ERROR(SILC_STATUS_ERR_RESOURCE_LIMIT);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Find client entry */
errors are handled in the resolving callback. */
COMMAND_ERROR(SILC_STATUS_ERR_NO_SUCH_NICK);
COMMAND_ERROR(SILC_STATUS_ERR_NO_SUCH_SERVER);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* No client or server exist with this name, query for both. */
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* SERVICE **********************************/
SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /SERVICE [<service name>] [-pubkey]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
name = cmd->argv[1];
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Register all default commands provided by the client library for the
silc_buffer_len(&packet->buffer));
if (!payload) {
SILC_LOG_DEBUG(("Bad command packet"));
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Get arguments */
case SILC_COMMAND_WHOIS:
/* Ignore everything if requested by application */
- if (client->internal->params->ignore_requested_attributes)
+ if (conn->internal->params.ignore_requested_attributes)
break;
silc_client_command_process_whois(client, conn, payload, args);
}
silc_command_payload_free(payload);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
ERROR_CALLBACK(cmd->error); \
silc_client_command_process_error(cmd, state_context, cmd->error); \
silc_fsm_next(fsm, silc_client_command_reply_processed); \
- return SILC_FSM_CONTINUE; \
+ SILC_FSM_CONTINUE; \
}
/* Check for correct arguments */
silc_argument_get_arg_num(args) > max) { \
ERROR_CALLBACK(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
silc_fsm_next(fsm, silc_client_command_reply_processed); \
- return SILC_FSM_CONTINUE; \
+ SILC_FSM_CONTINUE; \
}
#define SAY cmd->conn->client->internal->ops->say
silc_packet_free(packet);
if (!payload) {
SILC_LOG_DEBUG(("Bad command reply packet"));
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
cmd_ident = silc_command_get_ident(payload);
SILC_LOG_DEBUG(("Unknown command reply %s, ident %d",
silc_get_command_name(command), cmd_ident));
silc_command_payload_free(payload);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Signal command thread that command reply has arrived */
silc_fsm_next(&cmd->thread, silc_client_command_reply_process);
silc_fsm_continue_sync(&cmd->thread);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Wait here for command reply to arrive from remote host */
silc_fsm_set_state_context(fsm, NULL);
silc_fsm_next_later(fsm, silc_client_command_reply_timeout,
cmd->cmd != SILC_COMMAND_PING ? 25 : 60, 0);
- return SILC_FSM_WAIT;
+ SILC_FSM_WAIT;
}
/* Timeout occurred while waiting command reply */
if (conn->internal->disconnected) {
SILC_LOG_DEBUG(("Command %s canceled", silc_get_command_name(cmd->cmd)));
silc_list_del(conn->internal->pending_commands, cmd);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
SILC_LOG_DEBUG(("Command %s timeout", silc_get_command_name(cmd->cmd)));
/* Timeout, reply not received in timely fashion */
silc_list_del(conn->internal->pending_commands, cmd);
ERROR_CALLBACK(SILC_STATUS_ERR_TIMEDOUT);
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
/* Process received command reply payload */
silc_fsm_next(fsm, silc_client_command_reply_service);
break;
default:
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
}
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/* Completes command reply processing */
if (cmd->status == SILC_STATUS_OK || cmd->status == SILC_STATUS_LIST_END ||
SILC_STATUS_IS_ERROR(cmd->status))
- return SILC_FSM_FINISH;
+ SILC_FSM_FINISH;
/* Add back to pending command reply list */
silc_mutex_lock(conn->internal->lock);
/** Wait more command payloads */
silc_fsm_next(fsm, silc_client_command_reply_wait);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** WHOIS *************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** WHOWAS ************************************/
out:
silc_client_unref_client(client, conn, client_entry);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** IDENTIFY **********************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** NICK ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** LIST ************************************/
/* There were no channels in the network. */
silc_client_command_callback(cmd, NULL, NULL, NULL, 0);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
CHECK_ARGS(3, 5);
out:
silc_client_unref_channel(client, conn, channel_entry);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* TOPIC ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* INVITE ***********************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** KILL ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** INFO ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** STATS ***********************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** PING ************************************/
silc_client_command_callback(cmd);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** JOIN ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** MOTD ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** UMODE ***********************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** CMODE ***********************************/
if (public_key)
silc_pkcs_public_key_free(public_key);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** CUMODE **********************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** KICK ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/******************************** SILCOPER **********************************/
silc_client_command_callback(cmd);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** OPER ************************************/
silc_client_command_callback(cmd);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* DETACH ***********************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** WATCH ***********************************/
silc_client_command_callback(cmd);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/*********************************** BAN ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** LEAVE ***********************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************* USERS ************************************/
out:
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** GETKEY **********************************/
if (public_key)
silc_pkcs_public_key_free(public_key);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/********************************** SERVICE *********************************/
silc_client_command_callback(cmd, service_list, name);
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
/*********************************** QUIT ***********************************/
SILC_FSM_STATE(silc_client_command_reply_quit)
{
silc_fsm_next(fsm, silc_client_command_reply_processed);
- return SILC_FSM_CONTINUE;
+ SILC_FSM_CONTINUE;
}
} SilcClientOperations;
/***/
-/****f* silcclient/SilcClientAPI/SilcNicknameFormatParse
- *
- * SYNOPSIS
- *
- * typedef void (*SilcNicknameFormatParse)(const char *nickname,
- * char **ret_nickname);
- *
- * DESCRIPTION
- *
- * A callback function provided by the application for the library in
- * SilcClientParams structure. This function parses the formatted
- * nickname string `nickname' and returns the true nickname to the
- * `ret_nickname' pointer. The library can call this function at
- * any time.
- *
- ***/
-typedef void (*SilcNicknameFormatParse)(const char *nickname,
- char **ret_nickname);
-
/****s* silcclient/SilcClientAPI/SilcClientParams
*
* NAME
to save the nicknames in the library in a certain format. Since
nicknames are not unique in SILC it is possible to have multiple same
nicknames. Using this format string it is possible to order the library
- to separate the multiple same nicknames from each other. The format
- types are defined below and they can appear in any order in the format
- string. If this is NULL then default format is used which is the
- default nickname without anything else. The string MUST be NULL
- terminated.
+ to separate the multiple same nicknames from each other. If this is
+ empty then default format is used which is the default nickname
+ without anything else. The string MUST be NULL terminated.
Following format types are available:
"%a!%n@%s" (fe. nick@server, 2!nick@server)
"%n@%H" (fe. nick@host.domain.com)
- By default this format is employed to the nicknames by the libary
- only when there appears multiple same nicknames. If the library has
- only one nickname cached the nickname is saved as is and without the
- defined format. If you want always to save the nickname in the defined
- format set the boolean field `nickname_force_format' to value TRUE.
+ Note that there must always be some separator characters around '%n'
+ format. It is not possible to put format characters before or after
+ '%n' without separators (such ash '@'). Also note that the separator
+ character should be a character that cannot be part of normal nickname.
*/
char nickname_format[32];
value. */
SilcBool nickname_force_format;
- /* A callback function provided by the application for the library to
- parse the nickname from the formatted nickname string. Even though
- the libary formats the nicknames the application knows generally the
- format better so this function should be provided for the library
- if the application sets the `nickname_format' field. The library
- will call this to get the true nickname from the provided formatted
- nickname string whenever it needs the true nickname. */
- SilcNicknameFormatParse nickname_parse;
-
- /* If this is set to TRUE then the client will ignore all incoming
- Requested Attributes queries and does not reply anything back. This
- usually leads into situation where server does not anymore send
- the queries after seeing that client does not reply anything back.
- If your application does not support Requested Attributes or you do
- not want to use them set this to TRUE. See SilcAttribute and
- silc_client_attribute_add for more information on attributes. */
- SilcBool ignore_requested_attributes;
-
/* If this is set to TRUE, the silcclient library will not register and
deregister the cipher, pkcs, hash and hmac algorithms. The application
itself will need to handle that. */
* the client ready to be run. One must call silc_client_run to run the
* client. Returns FALSE if error occurred, TRUE otherwise.
*
- * The `username', `hostname' and `realname' strings must be given and
- * they must be UTF-8 encoded. The `username' is the client's username
- * in the operating system, `hostname' is the client's host name and
- * the `realname' is the user's real name.
+ * The `username' and `hostname' strings must be given and they must be
+ * UTF-8 encoded. The `username' is the client's username in the
+ * operating system, `hostname' is the client's host name and the
+ * `realname' is the user's real name.
*
* The `running' callback is called after the client is running after
* silc_client_run or silc_client_run_one has been called. Application
SilcUInt32 auth_len;
/* If this boolean is set to TRUE then the connection will use UDP instead
- of TCP. If UDP is set the also the next `local_ip' and `local_port'
+ of TCP. If UDP is set then also the next `local_ip' and `local_port'
must be set. */
SilcBool udp;
(3600 seconds, 1 hour). */
unsigned int rekey_secs;
+ /* If this is set to TRUE then the client will ignore all incoming
+ Requested Attributes queries and does not reply anything back. This
+ usually leads into situation where server does not anymore send
+ the queries after seeing that client does not reply anything back.
+ If your application does not support Requested Attributes or you do
+ not want to use them set this to TRUE. See SilcAttribute and
+ silc_client_attribute_add for more information on attributes. */
+ SilcBool ignore_requested_attributes;
+
} SilcClientConnectionParams;
/***/
* There can be only one active key agreement for `client_entry'. Old
* key agreement may be aborted by calling silc_client_abort_key_agreement.
*
+ * EXAMPLE
+ *
+ * // Send key agreement request (we don't provide connection endpoint)
+ * silc_client_send_key_agreement(client, conn, remote_client,
+ * NULL, public_key, private_key,
+ * my_keyagr_completion, my_context);
+ *
+ * // Another example where we provide connection endpoint (TCP).
+ * SilcClientConnectionParams params;
+ * memset(¶ms, 0, sizeof(params));
+ * params.local_ip = local_ip;
+ * params.local_port = local_port;
+ * params.timeout_secs = 60;
+ * silc_client_send_key_agreement(client, conn, remote_client,
+ * ¶ms, public_key, private_key,
+ * my_keyagr_completion, my_context);
+ *
***/
void silc_client_send_key_agreement(SilcClient client,
SilcClientConnection conn,
***/
SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...);
+/****f* silcclient/SilcClientAPI/silc_client_nickname_format
+ *
+ * SYNOPSIS
+ *
+ * SilcClientEntry
+ * silc_client_nickname_format(SilcClient client,
+ * SilcClientConnection conn,
+ * SilcClientEntry client_entry,
+ * SilcBool priority);
+ *
+ * DESCRIPTION
+ *
+ * Formats the nickname of `client_entry' according to the nickname
+ * formatting rules set in SilcClientParams. If the `priority' is TRUE
+ * then the `client_entry' will always get the unformatted nickname.
+ * If FALSE and there are more than one same nicknames in the client
+ * the nickname will be formatted.
+ *
+ * This returns NULL on error. Otherwise, the client entry that was
+ * formatted is returned. If `priority' is FALSE this always returns
+ * the `client_entry'. If it is TRUE, this may return the client entry
+ * that was formatted after giving the `client_entry' the unformatted
+ * nickname.
+ *
+ * Usually application does not need to call this function, as the library
+ * automatically formats nicknames. However, if application wants to
+ * for example force the `client_entry' to always have the unformatted
+ * nickname it may call this function to do so.
+ *
+ ***/
+SilcClientEntry silc_client_nickname_format(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry,
+ SilcBool priority);
+
#ifdef __cplusplus
}
#endif