+ notify->packet = packet;
+ notify->payload = payload;
+ notify->fsm = fsm;
+ silc_fsm_set_state_context(fsm, notify);
+
+ /* Process the notify */
+ switch (silc_notify_get_type(payload)) {
+
+ case SILC_NOTIFY_TYPE_NONE:
+ /** NONE */
+ silc_fsm_next(fsm, silc_client_notify_none);
+ break;
+
+ case SILC_NOTIFY_TYPE_INVITE:
+ /** INVITE */
+ silc_fsm_next(fsm, silc_client_notify_invite);
+ break;
+
+ case SILC_NOTIFY_TYPE_JOIN:
+ /** JOIN */
+ silc_fsm_next(fsm, silc_client_notify_join);
+ break;
+
+ case SILC_NOTIFY_TYPE_LEAVE:
+ /** LEAVE */
+ silc_fsm_next(fsm, silc_client_notify_leave);
+ break;
+
+ case SILC_NOTIFY_TYPE_SIGNOFF:
+ /** SIGNOFF */
+ silc_fsm_next(fsm, silc_client_notify_signoff);
+ break;
+
+ case SILC_NOTIFY_TYPE_TOPIC_SET:
+ /** TOPIC_SET */
+ silc_fsm_next(fsm, silc_client_notify_topic_set);
+ break;
+
+ case SILC_NOTIFY_TYPE_NICK_CHANGE:
+ /** NICK_CHANGE */
+ silc_fsm_next(fsm, silc_client_notify_nick_change);
+ break;
+
+ case SILC_NOTIFY_TYPE_CMODE_CHANGE:
+ /** CMODE_CHANGE */
+ silc_fsm_next(fsm, silc_client_notify_cmode_change);
+ break;
+
+ case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
+ /** CUMODE_CHANGE */
+ silc_fsm_next(fsm, silc_client_notify_cumode_change);
+ break;
+
+ case SILC_NOTIFY_TYPE_MOTD:
+ /** MOTD */
+ silc_fsm_next(fsm, silc_client_notify_motd);
+ break;
+
+ case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
+ /** CHANNEL_CHANGE */
+ silc_fsm_next(fsm, silc_client_notify_channel_change);
+ break;
+
+ case SILC_NOTIFY_TYPE_KICKED:
+ /** KICKED */
+ silc_fsm_next(fsm, silc_client_notify_kicked);
+ break;
+
+ case SILC_NOTIFY_TYPE_KILLED:
+ /** KILLED */
+ silc_fsm_next(fsm, silc_client_notify_killed);
+ break;
+
+ case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
+ /** SERVER_SIGNOFF */
+ silc_fsm_next(fsm, silc_client_notify_server_signoff);
+ break;
+
+ case SILC_NOTIFY_TYPE_ERROR:
+ /** ERROR */
+ silc_fsm_next(fsm, silc_client_notify_error);
+ break;
+
+ case SILC_NOTIFY_TYPE_WATCH:
+ /** WATCH */
+ silc_fsm_next(fsm, silc_client_notify_watch);
+ break;
+
+ default:
+ /** Unknown notify */
+ silc_notify_payload_free(payload);
+ silc_packet_free(packet);
+ silc_free(notify);
+ return SILC_FSM_FINISH;
+ break;
+ }
+
+ return SILC_FSM_CONTINUE;
+}
+
+/* Notify processed, finish the packet processing thread */
+
+SILC_FSM_STATE(silc_client_notify_processed)
+{
+ SilcClientNotify notify = state_context;
+ SilcPacket packet = notify->packet;
+ SilcNotifyPayload payload = notify->payload;
+
+ silc_notify_payload_free(payload);
+ silc_packet_free(packet);
+ silc_free(notify);
+ return SILC_FSM_FINISH;
+}
+
+/********************************** NONE ************************************/
+
+SILC_FSM_STATE(silc_client_notify_none)
+{
+ SilcClientConnection conn = fsm_context;
+ SilcClient client = conn->client;
+ SilcClientNotify notify = state_context;
+ SilcNotifyPayload payload = notify->payload;
+ SilcNotifyType type = silc_notify_get_type(payload);
+ SilcArgumentPayload args = silc_notify_get_args(payload);
+
+ SILC_LOG_DEBUG(("Notify: NONE"));
+
+ /* Notify application */
+ NOTIFY(client, conn, type, silc_argument_get_arg_type(args, 1, NULL));
+
+ /** Notify processed */
+ silc_fsm_next(fsm, silc_client_notify_processed);
+ return SILC_FSM_CONTINUE;
+}
+
+/********************************* INVITE ***********************************/
+
+/* Someone invite me to a channel */
+
+SILC_FSM_STATE(silc_client_notify_invite)
+{
+ SilcClientConnection conn = fsm_context;
+ SilcClient client = conn->client;
+ SilcClientNotify notify = state_context;
+ SilcNotifyPayload payload = notify->payload;
+ SilcNotifyType type = silc_notify_get_type(payload);
+ SilcArgumentPayload args = silc_notify_get_args(payload);
+ SilcClientEntry client_entry;
+ SilcChannelEntry channel = NULL;
+ unsigned char *tmp;
+ SilcUInt32 tmp_len;
+ SilcID id;
+
+ SILC_LOG_DEBUG(("Notify: INVITE"));
+
+ /* Get Channel ID */
+ if (!silc_argument_get_decoded(args, 1, SILC_ARGUMENT_ID, &id, NULL))
+ goto out;
+
+ /* Get the channel name */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)