Added SILC Server library.
[silc.git] / lib / silcserver / server_st_command.c
1 /*
2
3   server_st_command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2005 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 "silcserver.h"
22 #include "server_internal.h"
23
24 /************************** Types and definitions ***************************/
25
26 #define SILC_SERVER_COMMAND_CHECK(min, max)                                  \
27 do {                                                                         \
28   SilcUInt32 _argc;                                                          \
29                                                                              \
30   SILC_LOG_DEBUG(("Start"));                                                 \
31                                                                              \
32   _argc = silc_argument_get_arg_num(args);                                   \
33   if (_argc < min) {                                                         \
34     SILC_LOG_DEBUG(("Not enough parameters in command"));                    \
35     silc_server_command_send_status_reply(cmd,                               \
36                                           silc_command_get(cmd->payload),    \
37                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
38                                           0);                                \
39     silc_server_command_free(cmd);                                           \
40     return SILC_FSM_FINISH;                                                  \
41   }                                                                          \
42   if (_argc > max) {                                                         \
43     SILC_LOG_DEBUG(("Too many parameters in command"));                      \
44     silc_server_command_send_status_reply(cmd,                               \
45                                           silc_command_get(cmd->payload),    \
46                                           SILC_STATUS_ERR_TOO_MANY_PARAMS,   \
47                                           0);                                \
48     silc_server_command_free(cmd);                                           \
49     return SILC_FSM_FINISH;                                                  \
50   }                                                                          \
51 } while(0)
52
53
54 /************************ Static utility functions **************************/
55
56 /* Sends simple status message as command reply packet */
57
58 static void
59 silc_server_command_send_status_reply(SilcServerCommand cmd,
60                                       SilcCommand command,
61                                       SilcStatus status,
62                                       SilcStatus error)
63 {
64   SilcBuffer buffer;
65
66   /* Statistics */
67   cmd->thread->server->stat.commands_sent++;
68
69   SILC_LOG_DEBUG(("Sending command status %d", status));
70   buffer =
71     silc_command_reply_payload_encode_va(command, status, error,
72                                          silc_command_get_ident(cmd->payload),
73                                          0);
74   silc_packet_send(cmd->packet->stream, SILC_PACKET_COMMAND_REPLY, 0,
75                    buffer->data, silc_buffer_len(buffer));
76   silc_buffer_free(buffer);
77 }
78
79 /* Sends command status reply with one extra argument. The argument
80    type must be sent as argument. */
81
82 static void
83 silc_server_command_send_status_data(SilcServerCommand cmd,
84                                      SilcCommand command,
85                                      SilcStatus status,
86                                      SilcStatus error,
87                                      SilcUInt32 arg_type,
88                                      const unsigned char *arg,
89                                      SilcUInt32 arg_len)
90 {
91   SilcBuffer buffer;
92
93   /* Statistics */
94   cmd->thread->server->stat.commands_sent++;
95
96   SILC_LOG_DEBUG(("Sending command status %d", status));
97
98   buffer =
99     silc_command_reply_payload_encode_va(command, status, 0,
100                                          silc_command_get_ident(cmd->payload),
101                                          1, arg_type, arg, arg_len);
102   silc_packet_send(cmd->packet->stream, SILC_PACKET_COMMAND_REPLY, 0,
103                    buffer->data, silc_buffer_len(buffer));
104   silc_buffer_free(buffer);
105 }
106
107 static void
108 silc_server_command_send_status_data2(SilcServerCommand cmd,
109                                       SilcCommand command,
110                                       SilcStatus status,
111                                       SilcStatus error,
112                                       SilcUInt32 arg_type1,
113                                       const unsigned char *arg1,
114                                       SilcUInt32 arg_len1,
115                                       SilcUInt32 arg_type2,
116                                       const unsigned char *arg2,
117                                       SilcUInt32 arg_len2)
118 {
119   SilcBuffer buffer;
120
121   /* Statistics */
122   cmd->thread->server->stat.commands_sent++;
123
124   SILC_LOG_DEBUG(("Sending command status %d", status));
125
126   buffer =
127     silc_command_reply_payload_encode_va(command, status, 0,
128                                          silc_command_get_ident(cmd->payload),
129                                          2, arg_type1, arg1, arg_len1,
130                                          arg_type2, arg2, arg_len2);
131   silc_packet_send(cmd->packet->stream, SILC_PACKET_COMMAND_REPLY, 0,
132                    buffer->data, silc_buffer_len(buffer));
133   silc_buffer_free(buffer);
134 }
135
136 void silc_server_command_pending_free(SilcServerThread thread,
137                                       SilcServerPending pending);
138
139
140 /**************************** Utility functions *****************************/
141
142 /* Gets command context from freelist or allocates a new one. */
143
144 SilcServerCommand silc_server_command_alloc(SilcServerThread thread)
145 {
146   SilcServerCommand cmd;
147
148   silc_mutex_lock(thread->server->lock);
149
150   /* Get command context from freelist or allocate new one. */
151   cmd = silc_list_get(thread->server->command_pool);
152   if (!cmd) {
153     silc_mutex_unlock(thread->server->lock);
154
155     cmd = silc_calloc(1, sizeof(*cmd));
156     if (!cmd)
157       return NULL;
158
159     SILC_LOG_DEBUG(("Allocating command context %p", cmd));
160
161     cmd->thread = thread;
162
163     return cmd;
164   }
165
166   SILC_LOG_DEBUG(("Get command context %p", cmd));
167
168   /* Delete from freelist */
169   silc_list_del(thread->server->command_pool, cmd);
170
171   cmd->thread = thread;
172
173   silc_mutex_unlock(thread->server->lock);
174
175   return cmd;
176 }
177
178 /* Puts the command context back to freelist */
179
180 void silc_server_command_free(SilcServerCommand cmd)
181 {
182   SilcServerThread thread = cmd->thread;
183
184   silc_mutex_lock(thread->server->lock);
185
186   /* Check for double free */
187 #if defined(SILC_DEBUG)
188   assert(cmd->packet != NULL);
189 #endif /* SILC_DEBUG */
190
191   if (cmd->packet)
192     silc_packet_free(cmd->packet);
193   cmd->packet = NULL;
194
195   if (cmd->pending)
196     silc_server_command_pending_free(thread, cmd->pending);
197
198   /* Put the packet back to freelist */
199   silc_list_add(thread->server->command_pool, cmd);
200
201   silc_mutex_unlock(thread->server->lock);
202 }
203
204 /* Returns pending context used to wait for a command reply. */
205
206 SilcServerPending silc_server_command_pending(SilcServerThread thread,
207                                               SilcUInt16 cmd_ident)
208 {
209   SilcServerPending pending;
210
211   silc_mutex_lock(thread->server->lock);
212
213   /* Check if pending already */
214   if (silc_hash_table_find(thread->server->pending_commands,
215                            SILC_32_TO_PTR(cmd_ident), NULL,
216                            (void **)&pending)) {
217     pending->refcnt++;
218     silc_mutex_unlock(thread->server->lock);
219     return pending;
220   }
221
222   pending = silc_calloc(1, sizeof(*pending));
223   if (!pending) {
224     silc_mutex_unlock(thread->server->lock);
225     return NULL;
226   }
227
228   silc_fsm_sema_init(&pending->wait_reply, &thread->fsm, 0);
229   pending->refcnt = 1;
230   pending->cmd_ident = cmd_ident;
231
232   /* Add to pending commands hash table */
233   if (!silc_hash_table_add(thread->server->pending_commands,
234                            SILC_32_TO_PTR(cmd_ident), pending)) {
235     silc_mutex_unlock(thread->server->lock);
236     silc_free(pending);
237     return NULL;
238   }
239
240   silc_mutex_unlock(thread->server->lock);
241
242   return pending;
243 }
244
245 /* Free's the pending command context */
246
247 void silc_server_command_pending_free(SilcServerThread thread,
248                                       SilcServerPending pending)
249 {
250   silc_mutex_lock(thread->server->lock);
251
252   pending->refcnt--;
253   if (pending->refcnt > 0) {
254     silc_mutex_unlock(thread->server->lock);
255     return;
256   }
257
258   /* If command reply context set, free it also */
259   if (pending->reply) {
260     pending->reply->pending = NULL;
261     silc_server_command_free(pending->reply);
262   }
263
264   /* Remove from pending commands */
265   silc_hash_table_del_by_context(thread->server->pending_commands,
266                                  SILC_32_TO_PTR(pending->cmd_ident), pending);
267   silc_free(pending);
268
269   silc_mutex_unlock(thread->server->lock);
270 }
271
272 /* Returns pending command context for command identifier */
273
274 SilcServerPending silc_server_command_pending_get(SilcServerThread thread,
275                                                   SilcUInt16 cmd_ident)
276 {
277   SilcServerPending pending = NULL;
278
279   silc_mutex_lock(thread->server->lock);
280   silc_hash_table_find(thread->server->pending_commands,
281                        SILC_32_TO_PTR(cmd_ident), NULL, (void **)&pending);
282   silc_mutex_unlock(thread->server->lock);
283
284   return pending;
285 }
286
287 /* Signals pending command waiters.  Used by command reply routines. */
288
289 void silc_server_command_pending_signal(SilcServerCommand cmd)
290 {
291   SilcServerThread thread = cmd->thread;
292   SilcServerPending pending = cmd->pending;
293
294   if (!pending)
295     return;
296
297   silc_mutex_lock(thread->server->lock);
298
299   /* Signal */
300   pending->reply = cmd;
301   SILC_FSM_SEMA_POST(&pending->wait_reply);
302
303   /* Remove from pending */
304   silc_hash_table_del_by_context(thread->server->pending_commands,
305                                  SILC_32_TO_PTR(pending->cmd_ident), pending);
306
307   silc_mutex_unlock(thread->server->lock);
308 }
309
310
311 /**************************** Command received ******************************/
312
313 /* Received a COMMAND packet.  We parse the packet and process the
314    requested command. */
315
316 SILC_FSM_STATE(silc_server_st_packet_command)
317 {
318   SilcServerThread thread = fsm_context;
319   SilcPacket packet = state_context;
320   SilcEntryData data = silc_packet_get_context(packet->stream);
321   SilcServerCommand cmd;
322   SilcUInt32 timeout = 0;
323
324   /* Allocate command context. */
325   cmd = silc_server_command_alloc(thread);
326   if (!cmd) {
327     silc_packet_free(packet);
328     return SILC_FSM_FINISH;
329   }
330
331   cmd->packet = packet;
332
333   /* Parse the command payload in the packet */
334   cmd->payload = silc_command_payload_parse(packet->buffer.data,
335                                             silc_buffer_len(&packet->buffer));
336   if (!cmd->payload) {
337     SILC_LOG_ERROR(("Bad command payload"));
338     silc_server_command_free(cmd);
339     return SILC_FSM_FINISH;
340   }
341
342   /* If client executes commands more frequently than once in 2 seconds,
343      apply 0 - 2 seconds of timeout to prevent flooding. */
344   if (data->type == SILC_CONN_CLIENT) {
345     SilcClientEntry client = (SilcClientEntry)data;
346
347     if (client->last_command && (time(NULL) - client->last_command) < 2) {
348       client->fast_command++;
349       if (client->fast_command > 5)
350         timeout = (client->fast_command < 3 ? 0 :
351                    2 - (time(NULL) - client->last_command));
352     } else {
353       if (client->fast_command - 2 <= 0)
354         client->fast_command = 0;
355       else
356         client->fast_command -= 2;
357     }
358   }
359
360   silc_fsm_set_state_context(fsm, cmd);
361
362   SILC_LOG_DEBUG(("Processing %s command (%d timeout)",
363                   silc_get_command_name(silc_command_get(cmd->payload)),
364                   timeout));
365
366   /* Process command */
367   switch (silc_command_get(cmd->payload)) {
368
369   case SILC_COMMAND_WHOIS:
370     /** Command WHOIS */
371     silc_fsm_next_later(fsm, silc_server_st_command_whois, timeout, 0);
372     break;
373
374   case SILC_COMMAND_WHOWAS:
375     /** Command WHOWAS */
376     silc_fsm_next_later(fsm, silc_server_st_command_whowas, timeout, 0);
377     break;
378
379   case SILC_COMMAND_IDENTIFY:
380     /** Command IDENTIFY */
381     silc_fsm_next_later(fsm, silc_server_st_command_identify, timeout, 0);
382     break;
383
384   case SILC_COMMAND_NICK:
385     /** Command NICK */
386     silc_fsm_next_later(fsm, silc_server_st_command_nick, timeout, 0);
387     break;
388
389   case SILC_COMMAND_LIST:
390     /** Command LIST */
391     silc_fsm_next_later(fsm, silc_server_st_command_list, timeout, 0);
392     break;
393
394   case SILC_COMMAND_TOPIC:
395     /** Command TOPIC */
396     silc_fsm_next_later(fsm, silc_server_st_command_topic, timeout, 0);
397     break;
398
399   case SILC_COMMAND_INVITE:
400     /** Command INVITE */
401     silc_fsm_next_later(fsm, silc_server_st_command_invite, timeout, 0);
402     break;
403
404   case SILC_COMMAND_QUIT:
405     /** Command QUIT */
406     silc_fsm_next_later(fsm, silc_server_st_command_quit, timeout, 0);
407     break;
408
409   case SILC_COMMAND_KILL:
410     /** Command KILL */
411     silc_fsm_next_later(fsm, silc_server_st_command_kill, timeout, 0);
412     break;
413
414   case SILC_COMMAND_INFO:
415     /** Command INFO */
416     silc_fsm_next_later(fsm, silc_server_st_command_info, timeout, 0);
417     break;
418
419   case SILC_COMMAND_STATS:
420     /** Command STATS */
421     silc_fsm_next_later(fsm, silc_server_st_command_stats, timeout, 0);
422     break;
423
424   case SILC_COMMAND_PING:
425     /** Command INFO */
426     silc_fsm_next_later(fsm, silc_server_st_command_ping, timeout, 0);
427     break;
428
429   case SILC_COMMAND_OPER:
430     /** Command OPER */
431     silc_fsm_next_later(fsm, silc_server_st_command_oper, timeout, 0);
432     break;
433
434   case SILC_COMMAND_JOIN:
435     /** Command JOIN */
436     silc_fsm_next_later(fsm, silc_server_st_command_join, timeout, 0);
437     break;
438
439   case SILC_COMMAND_MOTD:
440     /** Command MOTD */
441     silc_fsm_next_later(fsm, silc_server_st_command_motd, timeout, 0);
442     break;
443
444   case SILC_COMMAND_UMODE:
445     /** Command UMODE */
446     silc_fsm_next_later(fsm, silc_server_st_command_umode, timeout, 0);
447     break;
448
449   case SILC_COMMAND_CMODE:
450     /** Command CMODE */
451     silc_fsm_next_later(fsm, silc_server_st_command_cmode, timeout, 0);
452     break;
453
454   case SILC_COMMAND_CUMODE:
455     /** Command CUMODE */
456     silc_fsm_next_later(fsm, silc_server_st_command_cumode, timeout, 0);
457     break;
458
459   case SILC_COMMAND_KICK:
460     /** Command KICK */
461     silc_fsm_next_later(fsm, silc_server_st_command_kick, timeout, 0);
462     break;
463
464   case SILC_COMMAND_BAN:
465     /** Command BAN */
466     silc_fsm_next_later(fsm, silc_server_st_command_ban, timeout, 0);
467     break;
468
469   case SILC_COMMAND_DETACH:
470     /** Command DETACH */
471     silc_fsm_next_later(fsm, silc_server_st_command_detach, timeout, 0);
472     break;
473
474   case SILC_COMMAND_WATCH:
475     /** Command WATCH */
476     silc_fsm_next_later(fsm, silc_server_st_command_watch, timeout, 0);
477     break;
478
479   case SILC_COMMAND_SILCOPER:
480     /** Command SILCOPER */
481     silc_fsm_next_later(fsm, silc_server_st_command_silcoper, timeout, 0);
482     break;
483
484   case SILC_COMMAND_LEAVE:
485     /** Command LEAVE */
486     silc_fsm_next_later(fsm, silc_server_st_command_leave, timeout, 0);
487     break;
488
489   case SILC_COMMAND_USERS:
490     /** Command USERS */
491     silc_fsm_next_later(fsm, silc_server_st_command_users, timeout, 0);
492     break;
493
494   case SILC_COMMAND_GETKEY:
495     /** Command GETKEY */
496     silc_fsm_next_later(fsm, silc_server_st_command_getkey, timeout, 0);
497     break;
498
499   case SILC_COMMAND_SERVICE:
500     /** Command SERVICE */
501     silc_fsm_next_later(fsm, silc_server_st_command_service, timeout, 0);
502     break;
503
504   default:
505     SILC_LOG_DEBUG(("Unknown command %d", silc_command_get(cmd->payload)));
506     silc_server_command_free(cmd);
507     return SILC_FSM_FINISH;
508     break;
509   }
510
511   /* Statistics */
512   thread->server->stat.commands_received++;
513
514   return timeout ? SILC_FSM_WAIT : SILC_FSM_CONTINUE;
515 }
516
517
518 /********************************** NICK ************************************/
519
520 SILC_FSM_STATE(silc_server_st_command_nick)
521 {
522   SilcServerThread thread = fsm_context;
523   SilcServerCommand cmd = state_context;
524   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
525
526   return SILC_FSM_FINISH;
527 }
528
529
530 /********************************** LIST ************************************/
531
532 SILC_FSM_STATE(silc_server_st_command_list)
533 {
534   SilcServerThread thread = fsm_context;
535   SilcServerCommand cmd = state_context;
536   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
537
538   return SILC_FSM_FINISH;
539 }
540
541
542 /********************************** TOPIC ***********************************/
543
544 SILC_FSM_STATE(silc_server_st_command_topic)
545 {
546   SilcServerThread thread = fsm_context;
547   SilcServerCommand cmd = state_context;
548   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
549
550   return SILC_FSM_FINISH;
551 }
552
553
554 /********************************* INVITE ***********************************/
555
556 SILC_FSM_STATE(silc_server_st_command_invite)
557 {
558   SilcServerThread thread = fsm_context;
559   SilcServerCommand cmd = state_context;
560   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
561
562   return SILC_FSM_FINISH;
563 }
564
565
566 /********************************** QUIT ************************************/
567
568 SILC_FSM_STATE(silc_server_st_command_quit)
569 {
570   SilcServerThread thread = fsm_context;
571   SilcServerCommand cmd = state_context;
572   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
573
574   return SILC_FSM_FINISH;
575 }
576
577
578 /********************************** KILL ************************************/
579
580 SILC_FSM_STATE(silc_server_st_command_kill)
581 {
582   SilcServerThread thread = fsm_context;
583   SilcServerCommand cmd = state_context;
584   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
585
586   return SILC_FSM_FINISH;
587 }
588
589
590 /********************************** INFO ************************************/
591
592 /* Server side of command INFO. This sends information about us to
593    the client.  If client requested specific server we will send the
594    command to that server. */
595
596 SILC_FSM_STATE(silc_server_st_command_info)
597 {
598   return SILC_FSM_FINISH;
599 }
600
601
602 /********************************** STATS ***********************************/
603
604 SILC_FSM_STATE(silc_server_st_command_stats)
605 {
606   SilcServerThread thread = fsm_context;
607   SilcServerCommand cmd = state_context;
608   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
609
610   return SILC_FSM_FINISH;
611 }
612
613
614 /********************************** PING ************************************/
615
616 /* Server side of command PING. */
617
618 SILC_FSM_STATE(silc_server_st_command_ping)
619 {
620   SilcServerThread thread = fsm_context;
621   SilcServerCommand cmd = state_context;
622   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
623   SilcUInt32 tmp_len;
624   unsigned char *tmp;
625   SilcServerID server_id;
626
627   SILC_SERVER_COMMAND_CHECK(1, 1);
628
629   /* Get Server ID */
630   tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
631   if (!tmp) {
632     silc_server_command_send_status_reply(cmd, silc_command_get(cmd->payload),
633                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
634                                           0);
635     goto out;
636   }
637   if (!silc_id_payload_parse_id(tmp, tmp_len, NULL, &server_id,
638                                 sizeof(server_id))) {
639     silc_server_command_send_status_data(cmd, silc_command_get(cmd->payload),
640                                          SILC_STATUS_ERR_BAD_SERVER_ID, 0,
641                                          2, tmp, tmp_len);
642     goto out;
643   }
644
645   if (SILC_ID_SERVER_COMPARE(&server_id, &thread->server->id)) {
646     /* Send our reply */
647     silc_server_command_send_status_reply(cmd, silc_command_get(cmd->payload),
648                                           SILC_STATUS_OK, 0);
649   } else {
650     silc_server_command_send_status_data(cmd, silc_command_get(cmd->payload),
651                                          SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
652                                          2, tmp, tmp_len);
653   }
654
655  out:
656   silc_server_command_free(cmd);
657   return SILC_FSM_FINISH;
658 }
659
660
661 /*********************************** OPER ***********************************/
662
663 SILC_FSM_STATE(silc_server_st_command_oper)
664 {
665   SilcServerThread thread = fsm_context;
666   SilcServerCommand cmd = state_context;
667   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
668
669   return SILC_FSM_FINISH;
670 }
671
672
673 /*********************************** JOIN ***********************************/
674
675 SILC_FSM_STATE(silc_server_st_command_join)
676 {
677   SilcServerThread thread = fsm_context;
678   SilcServerCommand cmd = state_context;
679   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
680
681   return SILC_FSM_FINISH;
682 }
683
684
685 /*********************************** MOTD ***********************************/
686
687 SILC_FSM_STATE(silc_server_st_command_motd)
688 {
689   SilcServerThread thread = fsm_context;
690   SilcServerCommand cmd = state_context;
691   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
692
693   return SILC_FSM_FINISH;
694 }
695
696
697 /*********************************** UMODE **********************************/
698
699 SILC_FSM_STATE(silc_server_st_command_umode)
700 {
701   SilcServerThread thread = fsm_context;
702   SilcServerCommand cmd = state_context;
703   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
704
705   return SILC_FSM_FINISH;
706 }
707
708
709 /*********************************** CMODE **********************************/
710
711 SILC_FSM_STATE(silc_server_st_command_cmode)
712 {
713   SilcServerThread thread = fsm_context;
714   SilcServerCommand cmd = state_context;
715   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
716
717   return SILC_FSM_FINISH;
718 }
719
720
721 /********************************** CUMODE **********************************/
722
723 SILC_FSM_STATE(silc_server_st_command_cumode)
724 {
725   SilcServerThread thread = fsm_context;
726   SilcServerCommand cmd = state_context;
727   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
728
729   return SILC_FSM_FINISH;
730 }
731
732
733 /*********************************** KICK ***********************************/
734
735 SILC_FSM_STATE(silc_server_st_command_kick)
736 {
737   SilcServerThread thread = fsm_context;
738   SilcServerCommand cmd = state_context;
739   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
740
741   return SILC_FSM_FINISH;
742 }
743
744
745 /*********************************** BAN ************************************/
746
747 SILC_FSM_STATE(silc_server_st_command_ban)
748 {
749   SilcServerThread thread = fsm_context;
750   SilcServerCommand cmd = state_context;
751   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
752
753   return SILC_FSM_FINISH;
754 }
755
756
757 /********************************** DETACH **********************************/
758
759 SILC_FSM_STATE(silc_server_st_command_detach)
760 {
761   SilcServerThread thread = fsm_context;
762   SilcServerCommand cmd = state_context;
763   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
764
765   return SILC_FSM_FINISH;
766 }
767
768
769 /********************************** WATCH ***********************************/
770
771 SILC_FSM_STATE(silc_server_st_command_watch)
772 {
773   SilcServerThread thread = fsm_context;
774   SilcServerCommand cmd = state_context;
775   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
776
777   return SILC_FSM_FINISH;
778 }
779
780
781 /********************************* SILCOPER *********************************/
782
783 SILC_FSM_STATE(silc_server_st_command_silcoper)
784 {
785   SilcServerThread thread = fsm_context;
786   SilcServerCommand cmd = state_context;
787   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
788
789   return SILC_FSM_FINISH;
790 }
791
792
793 /********************************** LEAVE ***********************************/
794
795 SILC_FSM_STATE(silc_server_st_command_leave)
796 {
797   SilcServerThread thread = fsm_context;
798   SilcServerCommand cmd = state_context;
799   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
800
801   return SILC_FSM_FINISH;
802 }
803
804
805 /********************************** USERS ***********************************/
806
807 SILC_FSM_STATE(silc_server_st_command_users)
808 {
809   SilcServerThread thread = fsm_context;
810   SilcServerCommand cmd = state_context;
811   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
812
813   return SILC_FSM_FINISH;
814 }
815
816
817 /********************************** GETKEY **********************************/
818
819 SILC_FSM_STATE(silc_server_st_command_getkey)
820 {
821   SilcServerThread thread = fsm_context;
822   SilcServerCommand cmd = state_context;
823   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
824
825   return SILC_FSM_FINISH;
826 }
827
828
829 /********************************** SERVICE *********************************/
830
831 SILC_FSM_STATE(silc_server_st_command_service)
832 {
833   SilcServerThread thread = fsm_context;
834   SilcServerCommand cmd = state_context;
835   SilcArgumentPayload args = silc_command_get_args(cmd->payload);
836
837   return SILC_FSM_FINISH;
838 }